- File и FileReader
- FileReader
- Итого
- How to Download Any File In JavaScript
- What are Data URLs
- Dynamically Creating a Download Link
- How to Download Blobs in JavaScript
- In Conclusion
- Recommended
- How to 3D Flip Images With CSS
- How to Force Rerender Components in Svelte
- The Quick Way to Add Env Variables to Svelte using Vite
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 .
How to Download Any File In JavaScript
In order to download any kind of file programmatically in JavaScript, we can use an invisible anchor with a download attribute. When the download attribute is set on an anchor, it will try to download the resource at the href attribute.
a href="/resources/report.pdf" download> a href="/resources/report.pdf" download="latest-reports.pdf">
By setting a value for the download attribute, we can specify a custom name for the downloaded file.
Of course, when we want to programmatically generate the file to be downloaded on the fly, we don’t have it available on the server, so there’s no URL to point the anchor to. To generate and download the file programmatically, we can use data URLs.
What are Data URLs
Data URLs are URLs prefixed with the data: scheme that allows us to inline small files into documents. We are going to use this approach to programmatically generate the resource that we want to download, in this example, a JSON file containing the necessary data. A data URL has the following format:
- The mediatype is a MIME type, such as image/jpeg or text/html . In our case, we will be using text/plain for plain text files. We are also going to need to set the character encoding to UTF-8 for the correct encoding format.
- There is an optional base64 string we can set in case we want to embed base64-encoded binary data. In our case, we can omit this value.
- Lastly, we have the actual data for the file. To convert the data into the correct URI string, we can use the built-in encodeURIComponent function.
This leaves us with the following for the data URL:
'data:text/plain;charset=utf-8,' + encodeURIComponent(data)
Level up your skills and master the art of frontend development with bite-sized tutorials.
We don’t spam. Unsubscribe anytime.
Looking to improve your skills? Check out our interactive course to master JavaScript from start to finish.
Dynamically Creating a Download Link
In order to use our Data URL, we also need to dynamically create a link. For this, we can use document.createElement . This will create an anchor for us, on which we can set the href and download attributes accordingly, and then programmatically click on the link in order to trigger a download. With everything combined, we can use the following function to download a programmatically generated JSON file.
const download = (data, filename) => const data = JSON.stringify(data) const link = document.createElement('a') link.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(data)) link.setAttribute('download', filename || 'data.json') link.style.display = 'none' document.body.appendChild(link) link.click() document.body.removeChild(link) > // Later call it like so: download( name: 'John Doe', email: '[email protected]', phone: '+1 234 567' >) // Calling with a custom file name download( name: 'John Doe' >, 'user.json')
This function accepts a JavaScript object that will be converted into JSON. It can also optionally accept a filename as the second parameter. When the link is created, we can set the appropriate attributes on it using the setAttribute method. We also want to set its display property to none , in order to prevent the link from showing up anywhere on the page.
After all necessary attributes are present on the link, we can append the element to the document, using the appendChild method, and trigger a click on the link to initiate the download. After the download of the resource has been started, we can remove the link from the document using the removeChild method.
How to Download Blobs in JavaScript
The above method, however, is limited. It doesn’t work with non-text-based files, and while we could change the MIME type, it also doesn’t work with files hosted elsewhere. In order to come around this, introduce you to blobs.
Using blobs is a more generic approach to download binary files, or files that are not programmatically generated, but hosted elsewhere. For this, we need to use the fetch API in combination with the URL.createObjectURL to create the correct URL for the blob, then use this for the href . Based on this, our code changes to the following:
const download = async (url, filename) => const data = await fetch(url) const blob = await data.blob() const objectUrl = URL.createObjectURL(blob) const link = document.createElement('a') link.setAttribute('href', objectUrl) link.setAttribute('download', filename) link.style.display = 'none' document.body.appendChild(link) link.click() document.body.removeChild(link) > // Later call it with an URL and filename like so: download('https://unpkg.com/[email protected]/umd/react.production.min.js', 'react.js')
In the above example, we are using async/await to fetch the resource at the provided URL. We can then transform the returned result by using the blob method on it. Lastly, we then generate the proper blob URL using URL.createObjectURL which expects a blob to be passed for it.
// The returned value of a blob > Blob size: 10737, type: 'application/javascript' > // The returned value of a blob URL > 'blob:http://localhost:8080/b813048a-2074-4333-ac10-0b81b9c5ca17'
Level up your skills and master the art of frontend development with bite-sized tutorials.
We don’t spam. Unsubscribe anytime.
Looking to improve your skills? Check out our interactive course to master JavaScript from start to finish.
In Conclusion
In conclusion, we can either use a data URL to download dynamically generated files on the fly or use the fetch API with URL.createObjectURL to download blobs and files from other domains. Do you also need to read back files in JavaScript and monitor their progress? Check out our tutorial below.
How to Open Any File in Javascript with Progressbar Using an ASCII text art in your search bar Learn how you can open and read any file in JavaScript, and also show the progress of the reading with an ASCII text art in your search bar. Learn More
📚 More Webtips
Level up your skills and master the art of frontend development with bite-sized tutorials.
We don’t spam. Unsubscribe anytime.
- Unlimited access to hundreds of tutorials
- Access to exclusive interactive lessons
- Remove ads to learn without distractions
Recommended
How to 3D Flip Images With CSS
How to Force Rerender Components in Svelte
The Quick Way to Add Env Variables to Svelte using Vite
Get access to 300+ webtips 💌
Level up your skills and master the art of frontend development with bite-sized tutorials.
We don’t spam. Unsubscribe anytime.