Перейти к основному содержимому

Чтение файлов в браузере

Разработчику

File API - чтение файлов в браузере

Страница может прочитать файл с диска пользователя до отправки на сервер — проверить размер, показать превью аватара, распарсить CSV в таблицу. Браузер не даёт произвольный доступ к файловой системе — только к файлам, которые пользователь явно выбрал или перетащил.

Связь: отправка на сервер — FormData; перетаскивание — drag-and-drop.


Типовые сценарии File API

СценарийЗадача
Профильаватар, документы
Админкаимпорт CSV
Публикацияпревью изображения до upload

Общий поток: выбор → проверка размера/типа на клиенте → превью → отправка на сервер. Ошибки формата и лимита лучше показывать до запроса, а не после ответа API.


Выбор файла через input

<label>
Аватар
<input type="file" id="avatar" accept="image/png,image/jpeg" />
</label>
<p id="preview"></p>

Разбор:

  • В этом фрагменте используется конструкция <label> как точка входа сценария.
  • Разметка задаёт опорные элементы интерфейса, к которым затем подключается JavaScript-логика.
  • Ключевые вызовы и свойства опираются на стандартные API JavaScript/браузера, поэтому шаблон легко перенести в реальный проект.
  • Такой пример удобно расширять обработкой ошибок, логированием и дополнительной валидацией входных данных.
АтрибутСмысл
acceptподсказка диалогу (MIME или расширения)
multipleнесколько файлов в input.files
captureна мобильных — камера вместо галереи

Код ITЗагрузка примера кода…

Разбор:

  • В этом фрагменте используется конструкция const input = document.getElementById('avatar'); как точка входа сценария.
  • Код показывает последовательность действий: получение данных, проверка условий и выполнение целевого действия.
  • Подписка через addEventListener связывает поведение с действием пользователя и отделяет логику от HTML-разметки.
  • Ключевые вызовы и свойства опираются на стандартные API JavaScript/браузера, поэтому шаблон легко перенести в реальный проект.
  • Такой пример удобно расширять обработкой ошибок, логированием и дополнительной валидацией входных данных.

input.files — живой FileList. После input.value = '' список очищается.


Объект File

Каждый выбранный файл — экземпляр File (наследник Blob).

СвойствоОписание
nameимя файла
sizeразмер в байтах
typeMIME (image/png, text/plain, может быть пустым)
lastModifiedметка времени
console.log(`${file.name}: ${(file.size / 1024).toFixed(1)} КБ, ${file.type}`);

Разбор:

  • Фрагмент выводит имя, размер в КБ и MIME-тип через console.log (см. блок javascript выше).
  • Код показывает последовательность действий: получение данных, проверка условий и выполнение целевого действия.
  • Ключевые вызовы и свойства опираются на стандартные API JavaScript/браузера, поэтому шаблон легко перенести в реальный проект.
  • Такой пример удобно расширять обработкой ошибок, логированием и дополнительной валидацией входных данных.

Проверяйте size и type на клиенте для UX, но повторяйте проверку на сервере — клиентские ограничения обходятся.


FileReader

FileReader читает Blob/File асинхронно в строку или бинарные данные.

МетодРезультат в reader.result
readAsText(file, encoding?)текст
readAsDataURL(file)строка data:image/png;base64,... — удобно для <img src>
readAsArrayBuffer(file)ArrayBuffer для бинарных форматов

События — load (успех), error, abort. В современном коде можно обернуть в Promise:

function readAsDataURL(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(reader.error);
reader.readAsDataURL(file);
});
}

async function showImagePreview(file, container) {
const url = await readAsDataURL(file);
container.innerHTML = `<img src="${url}" alt="Превью" width="120">`;
}

Разбор:

  • В этом фрагменте используется конструкция function readAsDataURL(file) { как точка входа сценария.
  • Код показывает последовательность действий: получение данных, проверка условий и выполнение целевого действия.
  • Используется асинхронное выполнение (async/await), поэтому интерфейс остаётся отзывчивым, пока операция не завершится.
  • Ключевые вызовы и свойства опираются на стандартные API JavaScript/браузера, поэтому шаблон легко перенести в реальный проект.
  • Такой пример удобно расширять обработкой ошибок, логированием и дополнительной валидацией входных данных.

После вставки превью через data URL для больших файлов помните об памяти: для продакшена часто используют URL.createObjectURL(file):

const url = URL.createObjectURL(file);
img.src = url;
img.onload = () => URL.revokeObjectURL(url);

Разбор:

  • В этом фрагменте используется конструкция const url = URL.createObjectURL(file); как точка входа сценария.
  • Код показывает последовательность действий: получение данных, проверка условий и выполнение целевого действия.
  • Ключевые вызовы и свойства опираются на стандартные API JavaScript/браузера, поэтому шаблон легко перенести в реальный проект.
  • Такой пример удобно расширять обработкой ошибок, логированием и дополнительной валидацией входных данных.

createObjectURL короче по памяти, чем base64, для крупных изображений.


Несколько файлов

input.multiple = true;

input.addEventListener('change', () => {
for (const file of input.files) {
console.log(file.name);
}
});

Разбор:

  • В этом фрагменте используется конструкция input.multiple = true; как точка входа сценария.
  • Код показывает последовательность действий: получение данных, проверка условий и выполнение целевого действия.
  • Подписка через addEventListener связывает поведение с действием пользователя и отделяет логику от HTML-разметки.
  • Ключевые вызовы и свойства опираются на стандартные API JavaScript/браузера, поэтому шаблон легко перенести в реальный проект.
  • Такой пример удобно расширять обработкой ошибок, логированием и дополнительной валидацией входных данных.

Или Array.from(input.files).filter(...) для валидации каждого элемента.


Отправка на сервер

Файлы уходят через FormData без ручного кодирования:

const formData = new FormData();
formData.append('avatar', file);
formData.append('userId', '42');

await fetch('/api/upload', { method: 'POST', body: formData });

Разбор:

  • В этом фрагменте используется конструкция const formData = new FormData(); как точка входа сценария.
  • Код показывает последовательность действий: получение данных, проверка условий и выполнение целевого действия.
  • Используется асинхронное выполнение (async/await), поэтому интерфейс остаётся отзывчивым, пока операция не завершится.
  • Ключевые вызовы и свойства опираются на стандартные API JavaScript/браузера, поэтому шаблон легко перенести в реальный проект.
  • Такой пример удобно расширять обработкой ошибок, логированием и дополнительной валидацией входных данных.

Не задавайте заголовок Content-Type вручную — браузер добавит multipart/form-data с границей.

Для JSON-API иногда читают файл в base64 и кладут в JSON — это увеличивает трафик; предпочтительнее отдельный multipart-эндпоинт.


Перетаскивание файлов

Тот же объект File приходит из dataTransfer.files в событии drop на зоне загрузки (см. drag-and-drop). Логику чтения (FileReader / createObjectURL) можно вынести в общую функцию.


Ограничения и безопасность

  • Скрипт не видит путь на диске (C:\Users\...) — только имя и содержимое.
  • Чтение больших файлов блокирует не поток, но память — показывайте прогресс, режьте на части (file.slice() + Blob) для очень больших загрузок.
  • Парсинг CSV/JSON из пользовательского файла — изолируйте ошибки, не выполняйте содержимое как код.

Практический сценарий — импорт CSV в интерфейс

Рабочий конвейер часто выглядит так:

  1. Пользователь выбирает .csv через <input type="file" accept=".csv,text/csv">.
  2. Клиент проверяет размер и тип файла.
  3. FileReader.readAsText читает файл.
  4. Скрипт валидирует заголовки и количество колонок.
  5. Предпросмотр первых 20 строк показывается в таблице.
  6. Подтверждённые данные отправляются на сервер батчами.

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


Частые ошибки

ОшибкаПоследствиеЧто делать
Проверка только расширения .csvфайл может быть другим по содержимомудополнительно проверять MIME и структуру данных
Весь файл читается в память сразузависания на больших файлахчитать частями через slice() и обрабатывать порциями
Использование innerHTML для содержимого файлаXSS-рискивыводить через textContent или санитайзер
Нет лимитов на размер в UIплохой UX и перегрузказаранее показывать допустимый максимум файла

Краткий итог

Пользователь выбирает файл → File в input.filesFileReader или URL.createObjectURL для превью → FormData + fetch для отправки. Пример FormData и POST — Fetch / axios — типовые запросы. Клиентская проверка размера и типа дополняет, но не заменяет серверную.