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

Метод readAsArrayBuffer для работы с файлами в JavaScript
Раздел: Файлы, Чтение
FileReader.readAsArrayBuffer(blob: Blob): undefined (result via onload event)

Функция FileReader.readAsArrayBuffer

Метод readAsArrayBuffer() принадлежит объекту FileReader в JavaScript. Он предназначен для асинхронного чтения содержимого указанного объекта Blob или File. После завершения чтения результат предоставляется в виде объекта ArrayBuffer, который представляет собой сырые бинарные данные.

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

Функция применяется, когда необходимо работать с содержимым файла на низком бинарном уровне. Это требуется для обработки файлов, которые не являются текстовыми (например, изображения, аудио, видео, PDF), для вычисления хэшей (например, SHA-256), для ручной разборки бинарных форматов или для передачи данных через сетевые API, такие как fetch с телом запроса в формате ArrayBuffer.

Аргументы

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

  • blob: Объект Blob или File, данные которого требуется прочитать. Объект File является наследником Blob.

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

Возвращаемые значения и события

Сама функция не возвращает значение. Для получения результата необходимо подписаться на события:

  • load: Срабатывает при успешном завершении чтения. Свойство reader.result будет содержать ArrayBuffer.
  • error: Срабатывает при невозможности прочитать файл. Свойство reader.error будет содержать объект ошибки DOMException.
  • loadend: Срабатывает по окончании операции (как при успехе, так и при ошибке).
  • progress: Периодически срабатывает во время чтения больших файлов, позволяя отслеживать прогресс.

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

Пример 1: Базовое чтение файла, выбранного через input.

<input type='file' id='fileInput' />
<script>
  document.getElementById('fileInput').addEventListener('change', function(event) {
    const file = event.target.files[0];
    if (!file) return;

    const reader = new FileReader();

    reader.onload = function(e) {
      const arrayBuffer = e.target.result;
      console.log('ArrayBuffer создан:', arrayBuffer);
      console.log('Длина в байтах:', arrayBuffer.byteLength);
    };

    reader.onerror = function(e) {
      console.error('Ошибка чтения:', reader.error);
    };

    reader.readAsArrayBuffer(file);
  });
</script>
// В консоли после выбора файла:
ArrayBuffer создан: ArrayBuffer {}
Длина в байтах: 12345

Пример 2: Чтение данных из объекта Blob, созданного вручную.

const text = 'Hello World!';
const blob = new Blob([text], { type: 'text/plain' });

const reader = new FileReader();
reader.onload = () => {
  const buffer = reader.result;
  const uint8Array = new Uint8Array(buffer);
  console.log('Байты Blob:', uint8Array);
};
reader.readAsArrayBuffer(blob);
Байты Blob: Uint8Array(12) [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]

Похожие функции в JavaScript

Объект FileReader предоставляет другие методы для чтения файлов в иных форматах:

  • readAsText(blob[, encoding]): Читает содержимое файла как текстовую строку. Удобен для работы с текстовыми файлами (JSON, CSV, код). Позволяет указать кодировку.
  • readAsDataURL(blob): Читает файл и возвращает строку в формате Data URL (например, data:image/png;base64,...). Широко используется для предварительного просмотра изображений.
  • readAsBinaryString(blob) (устаревший): Читает файл как строку, где каждый символ представляет один байт. Считается устаревшим, readAsArrayBuffer является предпочтительной заменой.

Критерии выбора

  • readAsArrayBuffer используют для прямой работы с бинарными данными, шифрования, хэширования.
  • readAsText применяют для текстовых данных.
  • readAsDataURL идеален для вставки медиафайлов непосредственно в HTML (например, в атрибут src тега img).

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

Ошибка 1: Попытка обратиться к результату до завершения операции чтения.

const file = new Blob(['test']);
const reader = new FileReader();
reader.readAsArrayBuffer(file);
// reader.result здесь будет null!
console.log(reader.result); // null
null

Решение: Всегда использовать обработчики событий (onload, addEventListener('load', ...)).

Ошибка 2: Необработанное событие ошибки.

const reader = new FileReader();
reader.onload = () => console.log('Успех');
// Если файл не существует или чтение прервано, ошибка не будет обработана.
reader.readAsArrayBuffer('несуществующий объект');
// В консоли может появиться неотловленное исключение DOMException.

Решение: Всегда добавлять обработчик onerror.

Ошибка 3: Повторное использование объекта FileReader после запуска операции.

const reader = new FileReader();
const blob1 = new Blob(['A']);
const blob2 = new Blob(['B']);

reader.onload = () => console.log('Чтение 1');
reader.readAsArrayBuffer(blob1);
// Следующий вызов до завершения первого вызовет ошибку.
reader.readAsArrayBuffer(blob2); // DOMException
DOMException: The object is already busy reading Blobs.

Решение: Для параллельного чтения нескольких файлов создавать новый экземпляр FileReader для каждого.

Изменения в последних версиях

Спецификация File API, частью которой является FileReader, остается относительно стабильной. Основные изменения касаются не самой функции readAsArrayBuffer, а окружающей её экосистемы:

  • Появление альтернативных, более современных API для асинхронного чтения файлов, таких как Blob.arrayBuffer(). Этот метод возвращает Promise, что позволяет использовать синтаксис async/await и является более предпочтительным в новом коде.
  • Улучшения в обработке больших файлов и потоковом чтении через ReadableStream из Streams API.

Сама функция readAsArrayBuffer сохраняет обратную совместимость, и её сигнатура не менялась.

Расширенные примеры

Пример 1: Вычисление SHA-256 хэша файла с помощью Web Crypto API.

Пример javascript
async function calculateFileHash(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = async (e) => {
      try {
        const buffer = e.target.result;
        // Вычисление хэша через Web Crypto API
        const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
        const hashArray = Array.from(new Uint8Array(hashBuffer));
        const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
        resolve(hashHex);
      } catch (err) {
        reject(err);
      }
    };
    reader.onerror = () => reject(reader.error);
    reader.readAsArrayBuffer(file);
  });
}
// Использование
fileInput.addEventListener('change', async (e) => {
  const hash = await calculateFileHash(e.target.files[0]);
  console.log('SHA-256:', hash);
});
SHA-256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

Пример 2: Ручной разбор заголовков бинарного файла (например, первых 4 байт как целого числа).

Пример javascript
function readFileHeader(file) {
  const reader = new FileReader();
  reader.onload = (e) => {
    const buffer = e.target.result;
    const dataView = new DataView(buffer);
    // Чтение 32-битного целого числа (big-endian) с позиции 0
    const magicNumber = dataView.getUint32(0, false);
    console.log('Magic number (hex):', magicNumber.toString(16));
  };
  // Читаем только первые 4 байта для анализа заголовка
  reader.readAsArrayBuffer(file.slice(0, 4));
}
Magic number (hex): 89504e47 // Сигнатура PNG файла

Пример 3: Отправка бинарных данных на сервер с помощью fetch.

Пример javascript
document.getElementById('uploadBtn').addEventListener('click', () => {
  const file = fileInput.files[0];
  const reader = new FileReader();
  reader.onload = () => {
    const arrayBuffer = reader.result;
    // Отправка ArrayBuffer напрямую в теле запроса
    fetch('/upload', {
      method: 'POST',
      headers: { 'Content-Type': 'application/octet-stream' },
      body: arrayBuffer
    }).then(response => console.log('Файл отправлен'));
  };
  reader.readAsArrayBuffer(file);
});

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

Концепция чтения файла в бинарный буфер присутствует во многих языках.

Python

Используют режим 'rb' (read binary) для открытия файла и метод read(), который возвращает объект bytes.

with open('image.jpg', 'rb') as file:
    byte_data = file.read()
    print(type(byte_data))  # <class 'bytes'>
    print(len(byte_data))   # Размер в байтах
<class 'bytes'>
10240

PHP

Функция file_get_contents() с флагом FILE_BINARY.

$binaryData = file_get_contents('document.pdf', FILE_BINARY);
echo strlen($binaryData); // Выводит размер
204800

C (стандартная библиотека)

Используют функции fopen с режимом 'rb' и fread.

#include <stdio.h>
int main() {
    FILE *file = fopen('data.bin', 'rb');
    unsigned char buffer[1024];
    size_t bytesRead = fread(buffer, 1, sizeof(buffer), file);
    printf('Прочитано %zu байт\n', bytesRead);
    fclose(file);
    return 0;
}
Прочитано 1024 байт

Ключевое отличие JavaScript-реализации — её асинхронная природа, что предотвращает блокировку основного потока браузера во время чтения больших файлов.

JS FileReader.readAsArrayBuffer function comments

En
FileReader.readAsArrayBuffer Reads the contents of a File or Blob as an ArrayBuffer