Javascript содержимое локального файла

File и FileReader

Объект File наследуется от объекта Blob и обладает возможностями по взаимодействию с файловой системой.

Есть два способа его получить.

Во-первых, есть конструктор, похожий на Blob :

new File(fileParts, fileName, [options])
  • fileParts – массив значений Blob / BufferSource /строки.
  • fileName – имя файла, строка.
  • options – необязательный объект со свойством:
    • lastModified – дата последнего изменения в формате таймстамп (целое число).

    Во-вторых, чаще всего мы получаем файл из или через перетаскивание с помощью мыши, или из других интерфейсов браузера. В этом случае файл получает эту информацию из ОС.

    Так как File наследует от Blob , у объектов File есть те же свойства плюс:

    В этом примере мы получаем объект File из :

       

    Через можно выбрать несколько файлов, поэтому input.files – псевдомассив выбранных файлов. Здесь у нас только один файл, поэтому мы просто берём input.files[0] .

    FileReader

    FileReader объект, цель которого читать данные из Blob (и, следовательно, из File тоже).

    Данные передаются при помощи событий, так как чтение с диска может занять время.

    let reader = new FileReader(); // без аргументов
    • readAsArrayBuffer(blob) – считать данные как ArrayBuffer
    • readAsText(blob, [encoding]) – считать данные как строку (кодировка по умолчанию: utf-8 )
    • readAsDataURL(blob) – считать данные как base64-кодированный URL.
    • abort() – отменить операцию.

    Выбор метода для чтения зависит от того, какой формат мы предпочитаем, как мы хотим далее использовать данные.

    • readAsArrayBuffer – для бинарных файлов, для низкоуровневой побайтовой работы с бинарными данными. Для высокоуровневых операций у File есть свои методы, унаследованные от Blob , например, slice , мы можем вызвать их напрямую.
    • readAsText – для текстовых файлов, когда мы хотим получить строку.
    • readAsDataURL – когда мы хотим использовать данные в src для img или другого тега. Есть альтернатива – можно не читать файл, а вызвать URL.createObjectURL(file) , детали в главе Blob.

    В процессе чтения происходят следующие события:

    • loadstart – чтение начато.
    • progress – срабатывает во время чтения данных.
    • load – нет ошибок, чтение окончено.
    • abort – вызван abort() .
    • error – произошла ошибка.
    • loadend – чтение завершено (успешно или нет).

    Когда чтение закончено, мы сможем получить доступ к его результату следующим образом:

    Наиболее часто используемые события – это, конечно же, load и error .

       

    Как упоминалось в главе Blob, FileReader работает для любых объектов Blob, а не только для файлов.

    Поэтому мы можем использовать его для преобразования Blob в другой формат:

    • readAsArrayBuffer(blob) – в ArrayBuffer ,
    • readAsText(blob, [encoding]) – в строку (альтернатива TextDecoder ),
    • readAsDataURL(blob) – в формат base64-кодированного URL.

    Для веб-воркеров доступен синхронный вариант FileReader , именуемый FileReaderSync.

    Его методы считывания read* не генерируют события, а возвращают результат, как это делают обычные функции.

    Но это только внутри веб-воркера, поскольку задержки в синхронных вызовах, которые возможны при чтении из файла, в веб-воркерах менее важны. Они не влияют на страницу.

    Итого

    File объекты наследуют от Blob .

    Помимо методов и свойств Blob , объекты File также имеют свойства name и lastModified плюс внутреннюю возможность чтения из файловой системы. Обычно мы получаем объекты File из пользовательского ввода, например, через или перетаскиванием с помощью мыши, в событии dragend .

    Объекты FileReader могут читать из файла или Blob в одном из трёх форматов:

    • Строка ( readAsText ).
    • ArrayBuffer ( readAsArrayBuffer ).
    • URL в формате base64 ( readAsDataURL ).

    Однако, во многих случаях нам не нужно читать содержимое файла. Как и в случае с Blob, мы можем создать короткий URL с помощью URL.createObjectURL(file) и использовать его в теге или . Таким образом, файл может быть загружен или показан в виде изображения, как часть canvas и т.д.

    А если мы собираемся отправить File по сети, то это также легко, поскольку в сетевые методы, такие как XMLHttpRequest или fetch , встроена возможность отсылки File .

    Источник

    JavaScript: чтение и запись файлов с помощью File System Access API

    В этой небольшой статье я хочу рассказать вам о File System Access API (далее — FSA ), позволяющем читать и записывать файлы в локальную систему пользователя с помощью браузера.

    Если вам это интересно, прошу под кат.

    К сожалению, на сегодняшний день FSA поддерживается только 34.68% браузеров: сюда входят все десктопные браузеры, за исключением Firefox .

    Возможности

    FSA расширяет объект window следующими методами:

    • showOpenFilePicker — для чтения файлов;
    • showSaveFilePicker — для записи файлов;
    • showDirectoryPicker — для чтения директории.

    Данные методы называются фабриками дескрипторов локальной файловой системы (local file system handle factories) и возвращают FileSystemHandle — сущность (entity) для работы с файлами ( FileSystemFileHandle ) или директориями ( FileSystemDirectoryHandle ), соответственно.

    FileSystemHandle содержит поле kind (вид, тип), значением которого может быть либо file , либо directory , и поле name (название файла или директории).

    Чтение файла

    Для получения сущности для чтения файла ( FileSystemFileHandle ) используется метод showOpenFilePicker :

    const [fileHandle] = await window.showOpenFilePicker(options)

    Общими для showOpenFilePicker и showSaveFilePicker являются настройки:

    • types?: object — разрешенные типы файлов;
    • excludeAcceptAllOption?: boolean — если имеет значение true , picker будет принимать/сохранять только файлы с типами, определенными в types .

    Значением поля types является объект со следующими свойствами:

    Специфичной для showOpenFilePicker настройкой является multiple?: boolean — если имеет значение true , picker будет принимать несколько файлов и возвращать массив FileSystemFileHandle .

    Для чтения содержимого файла с помощью FileSystemFileHandle используется метод getFile :

    const file = await fileHandle.getFile()

    getFile возвращает интерфейс File . Для преобразования blob в текст можно использовать метод text (данный метод наследуется File от интерфейса Blob ):

    const fileContent = await file.text()

    Предположим, что у нас имеется директория fsa-test , в которой лежит файл test.txt с текстом Hi World . Прочитаем этот файл.

    Пользователь должен явно выразить намерение прочитать файл или директорию, например, нажать кнопку.

    const filePicker$ = document.querySelector('.file-picker') filePicker$.addEventListener('click', async () => < const [fileHandle] = await window.showOpenFilePicker() const file = await fileHandle.getFile() const fileContent = await file.text() console.log(fileContent) >)

    Нажимаем на кнопку. Выбираем файл test.txt . Получаем Hi World в консоли.

    Создадим еще парочку файлов, например, test2.txt с текстом Bye World и test3.txt с текстом Hi World Once Again .

    Прочитаем все 3 файла, запретив пользователю выбирать другие файлы.

    // настройки const options = < // можно выбирать несколько файлов multiple: true, // разрешенный тип файлов types: [ < description: 'Text', accept: < 'text/plain': '.txt' // разрешаем изображения // 'image/*': ['.jpg', '.jpeg', '.png', '.gif'] >> ], // можно выбирать только разрешенные файлы // по моим наблюдениям, данная настройка работает не совсем корректно excludeAcceptAllOption: true > filePicker$.addEventListener('click', async () => < const fileHandles = await window.showOpenFilePicker(options) const allFilesContent = await Promise.all( fileHandles.map(async (fileHandle) =>< const file = await fileHandle.getFile() const fileContent = await file.text() return fileContent >) ) console.log(allFilesContent.join('\n')) >)

    Нажимаем на кнопку. Выбираем файлы test.txt , test2.txt и test3.txt . Получаем в консоли:

    Hi World Bye World Hi World Once Again

    Запись файлов

    Для получения сущности для записи файла ( FileSystemFileHandle ) используется метод showSaveFilePicker :

    const fileHandle = await window.showSaveFilePicker(options)

    Специфичной для showSaveFilePicker является настройка suggestedName?: string — рекомендуемое название создаваемого файла.

    Для записи файла с помощью FileSystemFileHandle используется метод createWritable :

    const writableStream = await fileHandle.createWritable(options)

    Единственной доступной на сегодняшний день настройкой createWritable является keepExistingData?: boolean — если имеет значение true , picker сохраняет данные, имеющиеся в файле на момент записи, в противном случае, содержимое файла перезаписывается.

    createWritable возвращает FileSystemWritableFileStream , предоставляющий метод write для записи файла:

    await writableStream.write(fileData)

    fileData — это данные для записи.

    Запишем файл test4.txt с текстом Bye World Once Again .

    const fileSaver$ = document.querySelector('.file-saver') // настройки const options = < // рекомендуемое название файла suggestedName: 'test4.txt', types: [ < description: 'Text', accept: < 'text/plain': '.txt' >> ], excludeAcceptAllOption: true > // данные для записи const fileData = 'Bye World Once Again' fileSaver$.addEventListener('click', async () => < const fileHandle = await window.showSaveFilePicker(options) const writableStream = await fileHandle.createWritable() await writableStream.write(fileData) // данный метод не упоминается в черновике спецификации, // хотя там говорится о необходимости закрытия потока // для успешной записи файла await writableStream.close() >)

    Нажимаем на кнопку File saver . Сохраняем файл. Видим, что в директории появился файл test4.txt с текстом Bye World Once Again .

    Перезапишем содержимое файла test.txt .

    const filePicker$ = document.querySelector('.file-picker') const fileSaver$ = document.querySelector('.file-saver') const fileData = 'Bye World' let fileHandle filePicker$.addEventListener('click', async () => < ;[fileHandle] = await window.showOpenFilePicker() const file = await fileHandle.getFile() const fileContent = await file.text() console.log(fileContent) >) fileSaver$.addEventListener('click', async () => < const writableStream = await fileHandle.createWritable(< // не работает! keepExistingData: true >) await writableStream.write(fileData) await writableStream.close() >)

    Нажимаем на кнопку File picker . Выбираем файл test.txt . Нажимаем на кнопку File saver . Получаем уведомление о том, что браузер сможет манипулировать файлом test.txt до закрытия всех вкладок. Нажимаем Сохранить . Открываем test.txt . Видим, что текст Hi World изменился на Bye World (текст Hi World должен был сохраниться, поскольку мы указали настройку keepExistingData: true ).

    Чтение директории

    Для получения сущности для чтения директории ( FileSystemDirectoryHandle ) используется метод showDirectoryPicker :

    const dirPicker = await window.showDirectoryPicker()

    Для перебора содержимого выбранной директории можно использовать следующие методы:

    • entries — возвращает массив массивов вида [name, handle] , где name — название сущности, а handle — FileSystemHandle ;
    • values — возвращает массив handle ;
    • keys — возвращает массив name .

    Переместим файлы test2.txt , test3.txt и test4.txt в директорию text и прочитаем содержимое директории fsa-test .

    Структура директории fsa-test :

    - index.html - script.js - test.txt - text - test2.txt - test3.txt - test4.txt
    const dirPicker$ = document.querySelector('.dir-picker') dirPicker$.addEventListener('click', async () => < const dirHandle = await window.showDirectoryPicker() for await (const entry of dirHandle.values()) < console.log(entry.kind, entry.name) >>)

    Нажимаем на кнопку Directory picker . Выбираем директорию fsa-test . Получаем уведомление о том, что наш сайт сможет просматривать файлы в выбранной директории. Нажимаем Просмотреть файлы . Получаем в консоли:

    file index.html file script.js file test.txt directory text

    Для получения FileSystemFileHandle и FileSystemDirectoryHandle , находящихся внутри выбранной директории предназначены методы getFileHandle и getDirectoryHandle , соответственно. Обязательным параметром, принимаемым этими методами, является name — название файла/директории.

    Прочитаем содержимое файла test.txt и директории text .

    const dirPicker$ = document.querySelector('.dir-picker') dirPicker$.addEventListener('click', async () => < const dirHandle = await window.showDirectoryPicker() const fileHandle = await dirHandle.getFileHandle('test.txt') // читаем содержимое файла `test.txt` const fileContent = await (await fileHandle.getFile()).text() console.log(fileContent) // читаем содержимое директории `text` const subDirHandle = await dirHandle.getDirectoryHandle('text') for await (const handle of subDirHandle.values()) < console.log(handle.kind, handle.name) >>)

    Нажимаем на кнопку Directory picker . Выбираем директорию fsa-test . Нажимаем Просмотреть файлы . Получаем в консоли:

    Bye World file test4.txt file test2.txt file test3.txt

    getFileHandle и getDirectoryHandle также принимают настройку create?: boolean — если имеет значение true , запрашиваемый файл/директория создается при отсутствии:

    const fileHandle = await dirHandle.getFileHandle('test5.txt', < create: true >)

    Удаление файла/директории

    Для удаления файла или директории предназначен метод FileSystemDirectoryHandle.removeEntry . Он принимает 2 параметра:

Оцените статью