File API
File API в JavaScript — мощный инструмент для работы с файлами на стороне клиента: выбор, чтение и управление файлами прямо в браузере.
File API в JavaScript: работа с файлами пользователя
File API в JavaScript — это мощный инструмент, позволяющий веб-разработчикам работать с файлами на стороне клиента: пользователи могут выбирать, читать и управлять файлами непосредственно в веб-приложениях. API находит применение в самых разных задачах: загрузка файлов, обработка пользовательского контента и файловые операции. В этой статье мы разберём, что такое File API, каковы его преимущества, когда его стоит использовать, и рассмотрим типичные сценарии применения.
Что такое File API?
File API — это JavaScript API, предоставляющий доступ к файлам, выбранным пользователем через поля загрузки файлов (<input type="file">) или перетащенным на веб-страницу. Он включает небольшое семейство интерфейсов, работающих совместно:
File— представляет один файл, выбранный пользователем. Содержит метаданные:name,size(в байтах),type(MIME-тип) иlastModified(метка времени).File— это особый видBlob.Blob— фрагмент неизменяемых двоичных данных («Binary Large Object»). КаждыйFileявляетсяBlob, но вы также можете создавать собственные blob-объекты для скачивания или загрузки. Подробнее см. в отдельной главе JavaScript Blob.FileList— коллекция, похожая на array, возвращаемая свойствомinput.files. К элементам обращаются по индексу[0]или перебирают итерацией.FileReader— асинхронный ридер, считывающий содержимое файла в память в виде текста, data URL илиArrayBuffer.
Поскольку всё это работает в браузере, вы можете проверять, валидировать и предварительно просматривать файлы до того, как они попадут на сервер.
File API только читает файлы, которые пользователь явно вам передал. Страница никогда не может незаметно открыть произвольные файлы с диска посетителя — это намеренное ограничение безопасности.
Методы чтения: краткий обзор
FileReader предоставляет четыре метода чтения. Выберите тот, который возвращает нужный вам формат:
| Метод | Тип результата | Типичное применение |
|---|---|---|
readAsText(file) | string | .txt, .csv, .json, исходный код |
readAsDataURL(file) | строка data: URL | предпросмотр изображений/аудио/видео через src |
readAsArrayBuffer(file) | ArrayBuffer | разбор двоичных данных, хэширование, побайтовый анализ |
readAsBinaryString(file) | string из байтов | устаревший вариант; предпочтительнее readAsArrayBuffer |
Современные браузеры также предоставляют методы на основе промисов непосредственно у blob-объекта: await file.text(), await file.arrayBuffer() и file.stream(). В новом коде они нередко заменяют FileReader и прекрасно сочетаются с async/await.
Когда использовать File API
File API особенно полезен, когда нужно:
- Обрабатывать загрузку файлов — позволить пользователям выбирать и отправлять файлы с устройства.
- Предварительно просматривать файлы — показать миниатюру выбранного изображения или содержимое документа до загрузки.
- Валидировать на стороне клиента — отклонить неверный MIME-тип или слишком большой файл до того, как тратить трафик на загрузку.
- Обрабатывать файлы локально — обрезать изображения, редактировать текст или разбирать CSV без обращения к серверу.
Для PDF есть важная оговорка: File API не создаёт PDF-файлы. Он только выбирает, читает и сохраняет файлы. Для создания PDF нужна библиотека, например jsPDF, а File API (через Blob) затем инициирует скачивание.
Базовый пример: чтение содержимого файла
Ниже приведён простой пример использования File API в JavaScript для чтения текстового файла, выбранного пользователем, и отображения его содержимого. Этот демо-пример поможет вам понять, как взаимодействовать с файлами на устройстве с помощью веб-технологий.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>File Reader Example</title>
</head>
<body>
<h1>Read Text File</h1>
<p>First, choose a text file, then click the 'Read File' button to see your file's contents.</p>
<input type="file" id="fileInput" accept=".txt" />
<button onclick="readFile()">Read File</button>
<pre id="fileContents"></pre>
<script>
function readFile() {
const fileInput = document.getElementById("fileInput");
const file = fileInput.files[0]; // Get the first file selected by the user
if (file) {
const reader = new FileReader();
reader.onload = function (e) {
const contents = e.target.result;
document.getElementById("fileContents").textContent = contents;
};
reader.onerror = function (e) {
console.error("Error reading file:", e.target.error.message);
};
reader.readAsText(file); // Read the file as text
} else {
alert("Please select a file.");
}
}
</script>
</body>
</html>В этом коде:
- Выбор файла: пользователь выбирает текстовый файл (с расширением .txt) с помощью элемента файлового ввода.
- Чтение файла: когда пользователь нажимает кнопку «Read File», выбранный файл читается как текст. Обратите внимание, что операции
FileReaderасинхронны: коллбэкonloadвыполняется только после полного прочтения файла. - Отображение файла: содержимое файла отображается в элементе
<pre>, что сохраняет форматирование текстового файла.
Этот пример наглядно демонстрирует возможности File API для чтения файлов, выбранных пользователем, и работы с ними в веб-приложении.
Получение метаданных файла
Нередко нужно узнать подробности о файле прежде, чем что-либо делать с ним — для валидации или чтобы показать пользователю информацию о выборе. Каждый объект File предоставляет эти метаданные синхронно, без какого-либо чтения:
const file = fileInput.files[0];
console.log(file.name); // e.g. "report.pdf"
console.log(file.type); // MIME type, e.g. "application/pdf"
console.log(file.size); // size in bytes, e.g. 12048
console.log(file.lastModified); // ms since the Unix epochРаспространённая задача — преобразовать количество байт в удобочитаемый формат:
function formatBytes(bytes) {
if (bytes === 0) return "0 B";
const units = ["B", "KB", "MB", "GB"];
const i = Math.floor(Math.log(bytes) / Math.log(1024));
return (bytes / Math.pow(1024, i)).toFixed(1) + " " + units[i];
}
console.log(formatBytes(0)); // "0 B"
console.log(formatBytes(900)); // "900.0 B"
console.log(formatBytes(2048)); // "2.0 KB"
console.log(formatBytes(5242880)); // "5.0 MB"Валидация файлов перед загрузкой
Клиентская валидация даёт пользователю мгновенную обратную связь и позволяет избежать бесполезной загрузки. Всегда повторяйте валидацию на сервере — проверки на клиенте удобны, но не гарантируют безопасность, так как их можно обойти.
function validateImage(file) {
const allowedTypes = ["image/png", "image/jpeg", "image/webp"];
const maxSize = 2 * 1024 * 1024; // 2 MB
if (!allowedTypes.includes(file.type)) {
return "Only PNG, JPEG, or WebP images are allowed.";
}
if (file.size > maxSize) {
return "File is too large (max 2 MB).";
}
return null; // null means "valid"
}
// Simulate two checks:
console.log(validateImage({ type: "image/gif", size: 1000 }));
// "Only PNG, JPEG, or WebP images are allowed."
console.log(validateImage({ type: "image/png", size: 500 }));
// nullПредпросмотр изображения перед загрузкой
Чтобы показать миниатюру выбранного изображения, прочитайте его как data URL и присвойте эту строку атрибуту src элемента <img>. Браузер декодирует base64-содержимое напрямую — сервер не задействован.
<input type="file" id="imageInput" accept="image/*" />
<img id="preview" alt="Preview" width="200" />
<script>
const input = document.getElementById("imageInput");
const preview = document.getElementById("preview");
input.addEventListener("change", () => {
const file = input.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (e) => {
preview.src = e.target.result; // a "data:image/...;base64,..." URL
};
reader.readAsDataURL(file);
});
</script>Для больших медиафайлов предпочтительнее использовать URL.createObjectURL(file) вместо data URL — это возвращает короткую ссылку blob: без копирования всего файла в строку. Не забудьте вызвать URL.revokeObjectURL(), когда предпросмотр больше не нужен, чтобы браузер освободил память.
Чтение файла с помощью современных промисов
В современных браузерах можно полностью обойтись без FileReader и использовать await с собственными методами blob-объекта. Это удобнее, когда вы уже находитесь внутри async-функции:
async function readTextFile(file) {
const text = await file.text();
return text.trim().split("\n").length; // count of lines
}
// Simulate a File with the same API as the real Blob:
const fakeFile = new Blob(["line 1\nline 2\nline 3"]);
readTextFile(fakeFile).then((lines) => console.log(lines)); // 3Загрузка файла на сервер
После выбора файла его можно отправить с помощью fetch и тела FormData. Браузер автоматически устанавливает корректные заголовки multipart/form-data — не задавайте Content-Type вручную:
async function uploadFile(file) {
const formData = new FormData();
formData.append("upload", file, file.name);
const response = await fetch("/api/upload", {
method: "POST",
body: formData,
});
return response.ok;
}Подробнее о модели запросов и ответов см. в главе Fetch API.
Типичные ошибки
FileReaderработает асинхронно. Результат доступен только внутриonload; чтениеreader.resultна следующей строке вернётnull.input.filesможет содержать несколько файлов. Добавьте атрибутmultipleк элементу ввода и переберитеFileList; иначе вы увидите толькоfiles[0].valueсбрасывается при отмене в некоторых браузерах. Повторный выбор того же файла может не вызвать событиеchange; заранее сбросьтеinput.value = "", если нужно его обнаружить.file.typeможет быть пустым. Для неизвестных расширений MIME-тип может оказаться""; никогда не полагайтесь только на него при проверке.- Object URL приводят к утечке памяти. Каждый вызов
URL.createObjectURL()должен быть дополнен вызовомURL.revokeObjectURL().
Заключение
File API в JavaScript даёт веб-разработчикам возможность работать с файлами пользователя непосредственно в веб-приложениях, открывая новые возможности для улучшения взаимодействия с пользователем и обеспечения бесперебойного пользовательского опыта. Создаёте ли вы загрузчик файлов, редактор документов или любое приложение, требующее файловых операций — File API снабдит вас инструментами для создания многофункциональных клиентских решений для работы с файлами.
Чтобы углубиться в тему, изучите главу JavaScript Blob о создании и скачивании собственных двоичных данных, Drag and Drop с JavaScript — о перетаскивании файлов на страницу, а также Fetch API — об отправке файлов на сервер.