FileReader.readAsDataURL: примеры (JAVASCRIPT)

Преобразование файлов в DataURL при помощи JavaScript FileReader
Раздел: Файлы, Чтение
FileReader.readAsDataURL(blob: Blob): undefined (result via onload event)

Описание метода readAsDataURL

Метод readAsDataURL() принадлежит объекту FileReader и предназначен для асинхронного чтения содержимого файла (или blob-объекта) и его преобразования в строку в формате Data URL.

Data URL представляет собой схему URI, где данные встраиваются непосредственно в строку в кодировке base64. Это удобно для отображения изображений или других файлов непосредственно в веб-странице без необходимости загрузки с сервера.

Когда используется:

  • Предпросмотр изображений, загружаемых пользователем, перед отправкой на сервер.
  • Встраивание небольших файлов (например, иконок, шрифтов) непосредственно в HTML или CSS.
  • Создание миниатюр изображений на стороне клиента.
  • Передача содержимого файла через веб-сокеты или другие каналы в виде строки.

Аргументы: метод принимает один обязательный параметр.

  • blob (объект Blob или File): исходный файл или blob-объект, содержимое которого нужно прочитать.

Возвращаемое значение: метод не возвращает значение напрямую. Результат операции доступен через обработчики событий объекта FileReader.

  • Событие load срабатывает при успешном завершении чтения. Результат (строка Data URL) хранится в свойстве reader.result.
  • Событие error срабатывает при ошибке чтения. Информация об ошибке доступна в свойстве reader.error.
  • Событие loadend срабатывает по окончании операции (как при успехе, так и при ошибке).

Базовые примеры использования

Пример 1: Предпросмотр выбранного изображения.

const fileInput = document.getElementById('imageInput');

fileInput.addEventListener('change', (event) => {
  const file = event.target.files[0];
  if (!file || !file.type.startsWith('image/')) {
    alert('Пожалуйста, выберите изображение.');
    return;
  }

  const reader = new FileReader();
  reader.onload = (e) => {
    document.getElementById('preview').src = e.target.result;
  };
  reader.onerror = (e) => {
    console.error('Ошибка чтения файла:', reader.error);
  };
  reader.readAsDataURL(file);
});
// Результат: в элементе с id='preview' отобразится выбранное изображение.

Пример 2: Чтение текстового файла (хотя для текста лучше использовать readAsText).

const reader = new FileReader();
const textBlob = new Blob(['Пример текста'], { type: 'text/plain' });

reader.onload = () => {
  console.log('Data URL текстового файла:', reader.result.substring(0, 50) + '...');
};
reader.readAsDataURL(textBlob);
// Результат в консоли: "Data URL текстового файла: data:text/plain;base64,0J..." (урезано)

Альтернативные методы FileReader в JavaScript

  • readAsText(blob[, encoding]): Читает содержимое файла как текстовую строку. Предпочтительнее для текстовых файлов (TXT, CSV, JSON, HTML). Позволяет указать кодировку.
  • readAsArrayBuffer(blob): Читает содержимое файла в виде ArrayBuffer. Используется для работы с бинарными данными на низком уровне, например, для декодирования аудио через Web Audio API или для манипуляций с байтами.
  • readAsBinaryString(blob) (устаревший): Читает файл как бинарную строку. Метод считается устаревшим в современных стандартах, вместо него рекомендуется использовать readAsArrayBuffer.

Выбор метода: readAsDataURL идеален для встраивания небольших медиафайлов (изображений, небольших аудио) непосредственно в документ. Для текстовой обработки данных логичнее применять readAsText. Для сложной работы с двоичными данными подходит readAsArrayBuffer.

Типичные ошибки

Ошибка 1: Попытка прочитать файл до его выбора пользователем.

const reader = new FileReader();
// fileInput.files[0] равен undefined, если ничего не выбрано
reader.readAsDataURL(fileInput.files[0]); // Ошибка: передан undefined
reader.onerror = () => {
  console.log(reader.error.name); // => NotReadableError
};
NotReadableError

Ошибка 2: Игнорирование типа файла. Data URL для больших файлов (например, видео) может быть огромным и негативно влиять на производительность.

// Если пользователь выберет файл размером 50 МБ
reader.onload = () => {
  // Строка result будет содержать несколько десятков миллионов символов
  // Это может "подвесить" вкладку браузера
  document.body.textContent = reader.result; // Крайне нежелательно
};

Ошибка 3: Неправильная обработка асинхронности. Попытка использовать результат до события load.

reader.readAsDataURL(file);
console.log(reader.result); // null, так как чтение еще не завершено
null

История изменений

Спецификация File API, включая объекты FileReader и метод readAsDataURL, была первоначально стандартизирована W3C. Существенных изменений в синтаксисе или аргументах метода не было.

Основные изменения касаются периферийных аспектов:

  • Уточнение и расширение списка кодов ошибок в свойстве FileReader.error.
  • Более строгое определение порядка и условий возникновения событий (loadstart, progress, load, loadend, error, abort).
  • Повышение согласованности работы с Blob-объектами, особенно в контексте File API и XMLHttpRequest.

Метод readAsBinaryString был перемещен в раздел устаревших функций, а readAsDataURL остался основным методом для получения base64-представления файла.

Расширенные примеры использования

Пример 1: Создание миниатюры изображения с использованием Canvas.

Пример javascript
function createThumbnail(file, maxWidth, maxHeight) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      const img = new Image();
      img.onload = () => {
        const canvas = document.createElement('canvas');
        let width = img.width;
        let height = img.height;
        if (width > height && width > maxWidth) {
          height *= maxWidth / width;
          width = maxWidth;
        } else if (height > maxHeight) {
          width *= maxHeight / height;
          height = maxHeight;
        }
        canvas.width = width;
        canvas.height = height;
        const ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0, 0, width, height);
        // Получаем Data URL миниатюры
        resolve(canvas.toDataURL('image/jpeg', 0.9));
      };
      img.src = e.target.result;
    };
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

// Использование
createThumbnail(imageFile, 150, 150).then(thumbnailDataURL => {
  console.log('Data URL миниатюры готов:', thumbnailDataURL.substring(0, 80));
});

Пример 2: Последовательное чтение нескольких файлов.

Пример javascript
function readFilesAsDataURLs(files) {
  const results = [];
  let index = 0;
  function readNext() {
    if (index >= files.length) {
      console.log('Все файлы прочитаны:', results);
      return;
    }
    const reader = new FileReader();
    reader.onload = (e) => {
      results.push(e.target.result);
      index++;
      readNext();
    };
    reader.readAsDataURL(files[index]);
  }
  readNext();
}

// Использование при выборе нескольких файлов
fileInput.addEventListener('change', (e) => {
  readFilesAsDataURLs(Array.from(e.target.files));
});

Пример 3: Интеграция с drag-and-drop.

Пример javascript
const dropZone = document.getElementById('dropZone');

dropZone.addEventListener('dragover', (e) => e.preventDefault());
dropZone.addEventListener('drop', (e) => {
  e.preventDefault();
  const files = Array.from(e.dataTransfer.files).filter(f => f.type.startsWith('image/'));
  files.forEach(file => {
    const reader = new FileReader();
    reader.onload = (event) => {
      const img = document.createElement('img');
      img.src = event.target.result;
      img.style.maxWidth = '200px';
      dropZone.appendChild(img);
    };
    reader.readAsDataURL(file);
  });
});

Аналоги функции в других языках программирования

Python: Модуль base64 позволяет кодировать бинарные данные.

import base64

with open('image.png', 'rb') as file:
    data_url = "data:image/png;base64," + base64.b64encode(file.read()).decode('utf-8')
print(data_url[:80])
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...

PHP: Функции base64_encode и file_get_contents.

$file_data = file_get_contents('document.pdf');
$base64 = base64_encode($file_data);
$data_url = 'data:application/pdf;base64,' . $base64;
echo substr($data_url, 0, 60) . '...';
data:application/pdf;base64,JVBERi0xLjQKJcOkw7zD...

Отличия: В JavaScript операция асинхронная и происходит в браузере без перезагрузки страницы. В Python и PHP операции синхронные и выполняются на сервере, требуя наличия файла в файловой системе сервера.

JS FileReader.readAsDataURL function comments

En
FileReader.readAsDataURL Reads the contents of a File or Blob and returns a data URL