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

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

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

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

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

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


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

<label>
Аватар
<input type="file" id="avatar" accept="image/png,image/jpeg" />
</label>
<p id="preview"></p>
АтрибутСмысл
acceptподсказка диалогу (MIME или расширения)
multipleнесколько файлов в input.files
captureна мобильных — камера вместо галереи
const input = document.getElementById('avatar');
const preview = document.getElementById('preview');

input.addEventListener('change', () => {
const file = input.files[0];
if (!file) return;

if (file.size > 2 * 1024 * 1024) {
alert('Файл больше 2 МБ');
input.value = '';
return;
}

showImagePreview(file, preview);
});

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}`);

Проверяйте 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">`;
}

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

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

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


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

input.multiple = true;

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

Или 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 });

Не задавайте заголовок 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 из пользовательского файла — изолируйте ошибки, не выполняйте содержимое как код.

Краткий итог

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


См. также

Другие статьи этого же раздела в боковом меню (как на странице «О разделе»).