W3docs

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 особенно полезен, когда нужно:

  1. Обрабатывать загрузку файлов — позволить пользователям выбирать и отправлять файлы с устройства.
  2. Предварительно просматривать файлы — показать миниатюру выбранного изображения или содержимое документа до загрузки.
  3. Валидировать на стороне клиента — отклонить неверный MIME-тип или слишком большой файл до того, как тратить трафик на загрузку.
  4. Обрабатывать файлы локально — обрезать изображения, редактировать текст или разбирать 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 — об отправке файлов на сервер.

Practice

Практика
Что можно делать с помощью File API в JavaScript?
Что можно делать с помощью File API в JavaScript?
Was this page helpful?