File and FileReader
A File object inherits from Blob and is extended with filesystem-related capabilities.
There are two ways to obtain it.
First, there’s a constructor, similar to Blob :
new File(fileParts, fileName, [options])
- fileParts – is an array of Blob/BufferSource/String values.
- fileName – file name string.
- options – optional object:
- lastModified – the timestamp (integer date) of last modification.
Second, more often we get a file from or drag’n’drop or other browser interfaces. In that case, the file gets this information from OS.
As File inherits from Blob , File objects have the same properties, plus:
That’s how we can get a File object from :
The input may select multiple files, so input.files is an array-like object with them. Here we have only one file, so we just take input.files[0] .
FileReader
FileReader is an object with the sole purpose of reading data from Blob (and hence File too) objects.
It delivers the data using events, as reading from disk may take time.
let reader = new FileReader(); // no arguments
- readAsArrayBuffer(blob) – read the data in binary format ArrayBuffer .
- readAsText(blob, [encoding]) – read the data as a text string with the given encoding ( utf-8 by default).
- readAsDataURL(blob) – read the binary data and encode it as base64 data url.
- abort() – cancel the operation.
The choice of read* method depends on which format we prefer, how we’re going to use the data.
- readAsArrayBuffer – for binary files, to do low-level binary operations. For high-level operations, like slicing, File inherits from Blob , so we can call them directly, without reading.
- readAsText – for text files, when we’d like to get a string.
- readAsDataURL – when we’d like to use this data in src for img or another tag. There’s an alternative to reading a file for that, as discussed in chapter Blob: URL.createObjectURL(file) .
As the reading proceeds, there are events:
- loadstart – loading started.
- progress – occurs during reading.
- load – no errors, reading complete.
- abort – abort() called.
- error – error has occurred.
- loadend – reading finished with either success or failure.
When the reading is finished, we can access the result as:
The most widely used events are for sure load and error .
Here’s an example of reading a file:
As mentioned in the chapter Blob, FileReader can read not just files, but any blobs.
We can use it to convert a blob to another format:
- readAsArrayBuffer(blob) – to ArrayBuffer ,
- readAsText(blob, [encoding]) – to string (an alternative to TextDecoder ),
- readAsDataURL(blob) – to base64 data url.
For Web Workers, there also exists a synchronous variant of FileReader , called FileReaderSync.
Its reading methods read* do not generate events, but rather return a result, as regular functions do.
That’s only inside a Web Worker though, because delays in synchronous calls, that are possible while reading from files, in Web Workers are less important. They do not affect the page.
Summary
File objects inherit from Blob .
In addition to Blob methods and properties, File objects also have name and lastModified properties, plus the internal ability to read from filesystem. We usually get File objects from user input, like or Drag’n’Drop events ( ondragend ).
FileReader objects can read from a file or a blob, in one of three formats:
- String ( readAsText ).
- ArrayBuffer ( readAsArrayBuffer ).
- Data url, base-64 encoded ( readAsDataURL ).
In many cases though, we don’t have to read the file contents. Just as we did with blobs, we can create a short url with URL.createObjectURL(file) and assign it to or
. This way the file can be downloaded or shown up as an image, as a part of canvas etc.
And if we’re going to send a File over a network, that’s also easy: network API like XMLHttpRequest or fetch natively accepts File objects.
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 .
Node.js для начинающих: основы работы с файлами
Сегодня мы поговорим о том, как работать с файловой системой средствами Node.js, рассмотрим базовые операции, выполняемые с файлами. К таким операциям относятся следующие:
- Создание файла
- Чтение файла
- Запись данных в файл
- Удаление файла
- Переименование файла
Модуль fs
В Node.js имеется стандартный модуль, fs (сокращение от File System), дающий разработчику средства для работы с файловой системой. Импортировать его в проект можно так:
Методы этого модуля представлены в синхронной и асинхронной формах. Функции обратного вызова, передаваемые асинхронным методам, принимают в качестве первого параметра объект ошибки, а в качестве второго — данные, возвращённые при успешном выполнении операции. Рассмотрим пример:
Метод .readFile() , о котором мы ещё поговорим, предназначен для чтения файлов. В этом примере у функции обратного вызова есть два параметра — err и data . В первый параметр попадают ошибки, которые могут возникнуть при попытке чтения файла, во втором оказываются данные, полученные после успешного выполнения операции. Обратите внимание на то, что .readFile() — это асинхронный метод модуля fs . Его синхронная версия называется .readFileSync() . Похожий подход используется и для именования других методов модуля.
Создание нового файла
Здесь метод fs.open() используется для создания нового файла. В качестве первого аргумента он принимает имя файла. Его второй аргумент представляет собой флаг, указывающий системе на то, что именно мы хотим сделать с файлом. В данном случае это флаг w (сокращение от writing), который указывает на то, что мы хотим открыть файл для записи. Метод .open() может принимать различные флаги. Вот некоторые из них:
- r : открыть файл для чтения
- r+ : открыть файл для чтения и записи
- rs : открыть файл для чтения в синхронном режиме
- w : открыть файл для записи
- a : открыть файл для записи данных в конец файла
- a+ : открыть файл для чтения и для записи данных в конец файла
This is a test file. We're learning about Node.js File System. The End.
Запись данных в файл
Поговорим о том, как дописать что-нибудь в файл:
Здесь мы используем метод .appendFile() для добавления данных в конец существующего файла. В качестве первого аргумента этот метод принимает имя файла, в качестве второго — данные, которые нужно добавить в конец файла. Третий аргумент — это, как обычно, функция обратного вызова.
После того, как код, показанный выше, успешно отработает, содержимое файла будет выглядеть так:
This is a test file. We're learning about Node.js File System. The End. This line is beyond the end.
Существует и другой способ записи данных в файл. Он подразумевает использование метода .writeFile() . Этот метод очень похож на .appendFile() , но у него есть одно важное отличие. Дело в том, что с помощью метода .appendFile() мы добавляем в файл новые данные после тех данных, которые в нём уже есть. А при использовании метода .writeFile() содержимое файла заменяется на новое. Испытаем этот метод:
После успешного выполнения операции в файле окажется следующий текст:
I'm the replacement you've been looking for.
Как видно, содержимое файла полностью заменено новым.
Чтение файла
Для чтения файлов модуль fs предоставляет метод .readFile() , пример использования которого мы уже видели. В качестве первого параметра он принимает имя файла, в качестве второго — кодировку. Третий параметр — функция обратного вызова. Попытаемся вывести в консоль содержимое файла testFile.txt с помощью этого метода:
Данные файла, выведенные в консоль
Теперь поговорим о переименовании файлов.
Переименование файла
Для переименования файлов используется метод .rename() :
Первый аргумент метода представляет собой имя существующего файла, второй — новое имя этого файла. После успешного вызова этого метода файл testFile.txt превращается в newTestFile.txt .
Удаление файла
Для удаления файлов используется метод .unlink() :
Успешный вызов этого метода приводит к удалению файла newTestFile.txt .
Итоги
В этом материале мы рассмотрели основы работы с файловой системой в среде Node.js. Если вы хотите более глубоко освоить эту тему — взгляните на этот материал из цикла публикаций по Node.js, почитайте документацию по модулю fs и постарайтесь испробовать на практике всё, о чём узнаете.
Уважаемые читатели! Используете ли вы для работы с файлами в Node.js стандартный модуль fs или что-то другое?