JavaScript File и FileReader
Работа с файлами в браузере через JavaScript: интерфейсы File и FileReader, чтение текста, изображений и бинарных данных с примерами кода.
Веб-приложения регулярно работают с файлами, выбранными пользователем: читают текстовый документ, предпросматривают изображение перед загрузкой или обрабатывают бинарные данные прямо в браузере. JavaScript решает эту задачу с помощью двух связанных интерфейсов. Интерфейс File описывает отдельный файл (его имя, размер и тип), а интерфейс FileReader читает содержимое этого файла асинхронно, не отправляя его на сервер.
В этом руководстве рассматривается, как получить File из элемента <input>, прочитать его с помощью FileReader, а также использовать новые методы на основе промисов — file.text() и file.arrayBuffer(). File — это специализированный вид Blob, поэтому большинство изученного здесь применимо и к блобам; общую картину см. в обзоре File API.
Интерфейс File в JavaScript
Интерфейс File представляет данные отдельного файла. Файлы обычно поступают из элемента <input type="file">, операции перетаскивания или Clipboard API. Поскольку File расширяет Blob, он несёт как содержимое файла, так и метаданные о нём.
Основные свойства интерфейса File
name: имя файла в виде строки, например"report.pdf".size: размер файла в байтах (число).type: MIME-тип в виде строки, например"image/png". Может быть"", если браузер не может его определить.lastModified: временная метка (миллисекунды с начала эпохи Unix), отражающая время последнего изменения файла.
Получение файлов из input
Элемент <input> для файлов предоставляет свойство files — объект FileList, похожий на массив. Используйте event.target.files[0] для первого файла, или задайте атрибут multiple и переберите files в цикле, чтобы обработать несколько файлов одновременно.
Пример: отображение информации о файле
Вот простой способ вывести информацию о файле, выбранном пользователем:
<input type="file" id="fileInput" />
<div id="fileInfo"></div>document.getElementById('fileInput').addEventListener('change', function(event) {
const file = event.target.files[0];
if (!file) return; // user cancelled the dialog
const modified = new Date(file.lastModified).toLocaleString();
const info = `File Name: ${file.name}<br>
File Size: ${file.size} bytes<br>
File Type: ${file.type || 'unknown'}<br>
Last Modified: ${modified}`;
document.getElementById('fileInfo').innerHTML = info;
});Работа с FileReader API
Интерфейс FileReader читает содержимое File или Blob асинхронно. Чтение запускается одним из методов readAs…, а результат обрабатывается через события — при этом основной поток не блокируется.
Методы FileReader
readAsText(file): читает файл как текстовую строку (опционально с указанной кодировкой).readAsDataURL(file): читает файл как Data URL в кодировке base64 — удобно для предпросмотра через<img src>.readAsArrayBuffer(file): читает файл какArrayBufferиз сырых байт для бинарной обработки.
События FileReader
Поскольку чтение асинхронно, обработчики назначаются до вызова метода readAs…:
onload: срабатывает при успешном завершении чтения; данные находятся вreader.result(также доступны черезevent.target.result).onerror: срабатывает при ошибке чтения; подробности можно узнать изreader.error.onprogress: периодически срабатывает во время чтения;event.loadedиevent.totalпозволяют отобразить индикатор прогресса для больших файлов.
Пример: чтение текстового файла
Следующий пример читает текстовый файл с помощью FileReader и показывает его содержимое, включая процент выполнения:
<input type="file" id="textInput" />
<div id="textOutput">Upload a text file please</div>document.getElementById('textInput').addEventListener('change', function(event) {
const file = event.target.files[0];
if (!file) return;
const output = document.getElementById('textOutput');
const reader = new FileReader();
reader.onprogress = function(e) {
if (e.lengthComputable) {
const percent = Math.round((e.loaded / e.total) * 100);
output.textContent = `Reading… ${percent}%`;
}
};
reader.onload = function(e) {
output.textContent = e.target.result;
};
reader.onerror = function() {
output.textContent = 'Error reading file: ' + reader.error;
};
reader.readAsText(file);
});Продвинутое чтение файлов: работа с разными типами данных
Чтение изображений как Data URL
Чтобы отобразить файл изображения, выбранный пользователем, можно прочитать его как Data URL с помощью метода readAsDataURL. Этот метод кодирует файл как строку в формате base64, которую можно использовать непосредственно в элементах изображений.
Пример: отображение изображения
<input type="file" id="imageInput" />
<div>Select an image file, please.</div>
<img id="imageDisplay" />document.getElementById('imageInput').addEventListener('change', function(event) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = function(e) {
document.getElementById('imageDisplay').src = e.target.result;
};
reader.onerror = function() {
document.getElementById('imageDisplay').style.display = 'none';
alert('Error reading image file.');
};
reader.readAsDataURL(file);
});Чтение бинарных файлов с ArrayBuffer
Для приложений, которым необходимо обрабатывать аудио, видео или любые бинарные данные, чтение файла как ArrayBuffer является ключевым. Этот метод предоставляет универсальный буфер бинарных данных, который можно обрабатывать или передавать в другие API, например Web Audio или WebGL.
Пример: обработка бинарных данных
<input type="file" id="binaryInput" />
<div id="binaryOutput">Select any file.</div>document.getElementById('binaryInput').addEventListener('change', function(event) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = function(e) {
const buffer = e.target.result;
// Process the binary data
const info = `Buffer Length: ${buffer.byteLength} bytes`;
document.getElementById('binaryOutput').innerHTML = info;
};
reader.onerror = function() {
document.getElementById('binaryOutput').innerHTML = 'Error reading binary file.';
};
reader.readAsArrayBuffer(file);
});Современный подход: file.text() и file.arrayBuffer()
FileReader появился до промисов, поэтому его API на основе событий может казаться многословным. Все современные браузеры добавляют методы, возвращающие промисы, прямо в File/Blob, что позволяет читать файлы через async/await:
file.text(): разрешается в содержимое файла как строку UTF-8.file.arrayBuffer(): разрешается вArrayBufferиз сырых байт.file.stream(): возвращаетReadableStreamдля обработки очень больших файлов по частям.
<input type="file" id="modernInput" />document.getElementById('modernInput').addEventListener('change', async function(event) {
const file = event.target.files[0];
if (!file) return;
try {
const text = await file.text();
console.log('First 100 characters:', text.slice(0, 100));
const buffer = await file.arrayBuffer();
const bytes = new Uint8Array(buffer);
console.log('Total bytes:', bytes.length);
console.log('First byte:', bytes[0]);
} catch (err) {
console.error('Could not read file:', err);
}
});Для нового кода предпочтительнее использовать эти методы на основе промисов — они органично сочетаются с async/await и try/catch. Прибегайте к FileReader, когда нужны события onprogress или требуется поддержка очень старых браузеров. Для отправки файлов на сервер возобновляемыми частями комбинируйте file.slice() с этими методами — см. возобновляемую загрузку файлов.
Заключение
Интерфейс File сообщает сведения о файле (имя, размер, тип, lastModified), тогда как FileReader и новые методы file.text() / file.arrayBuffer() на основе промисов позволяют читать его содержимое без обращения к серверу. Вместе они закрывают типичные задачи: отображение метаданных файла, предпросмотр изображений, разбор текста и обработка бинарных данных целиком в браузере.
Для углублённого изучения исследуйте тип Blob, на котором построен File, и общий обзор File API.