Как получить файл из input type file
Перейти к содержимому

Как получить файл из input type file

  • автор:

 

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 :

  • 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 <input type="file"> 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:

    • name – the file name,
    • lastModified – the timestamp of last modification.

    That’s how we can get a File object from <input type="file"> :

    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.

    The main methods:

    • 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:

    • reader.result is the result (if successful)
    • reader.error is the error (if failed).

    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 <input> 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 <a> or <img> . 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 :

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

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

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

      • name – имя файла,
      • lastModified – таймстамп для даты последнего изменения.

      В этом примере мы получаем объект File из <input type="file"> :

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

      FileReader

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

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

      • 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 – чтение завершено (успешно или нет).

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

      • reader.result результат чтения (если оно успешно)
      • reader.error объект ошибки (при неудаче).

      Наиболее часто используемые события – это, конечно же, 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 из пользовательского ввода, например, через <input> или перетаскиванием с помощью мыши, в событии dragend .

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

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

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

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

      Reading files in JavaScript using the file APIs

      HTML5 finally provides a standard way to interact with local files, via the File API specification. As examples of its capabilities, the File API could be used to create a thumbnail preview of images as they’re sent to the server, or to allow an app to save a file reference while the user is offline. Additionally, you could use client-side logic to verify that an upload’s MIME type matches its file extension or to restrict the size of an upload.

      The specification provides several interfaces for accessing files from a local filesystem:

      1. File — an individual file; provides read-only information such as name, file size, MIME type, and a reference to the file handle.
      2. FileList — an array-like sequence of File objects. (Think <input type="file" multiple> or dragging a directory of files from the desktop.)
      3. Blob — Allows for slicing a file into byte ranges.

      When used in conjunction with the above data structures, the FileReader interface can be used to asynchronously read a file through familiar JavaScript event handling. Thus, it is possible to monitor the progress of a read, catch errors, and determine when a load is complete. In many ways the APIs resemble XMLHttpRequest ‘s event model.

      Selecting files

      The first thing to do is check that your browser fully supports the File API:

      Of course, if your app will only use some of these APIs, modify this snippet accordingly.

      Using form input for selecting

      The most straightforward way to load a file is to use a standard <input type="file"> element. JavaScript returns the list of selected File objects as a FileList . Here’s an example that uses the multiple attribute to allow selecting several files at once:

      Example: Using form input for selecting. Try it here!

      Using drag and drop for selecting

      Another technique for loading files is native drag and drop from the desktop to the browser. We can modify the previous example slightly to include drag and drop support.

      Example: Using drag and drop for selecting. Try it here!

      Note: Some browsers treat <input type="file"> elements as native drop targets. Try dragging files onto the input field in the previous example.

      Reading files

      Now comes the fun part!

      After you’ve obtained a File reference, instantiate a FileReader object to read its contents into memory. When the load finishes, the reader’s onload event is fired and its result attribute can be used to access the file data.

      FileReader includes four options for reading a file, asynchronously:

      • FileReader.readAsBinaryString(Blob|File) — The result property will contain the file/blob’s data as a binary string. Every byte is represented by an integer in the range [0…255].
      • FileReader.readAsText(Blob|File, opt_encoding) — The result property will contain the file/blob’s data as a text string. By default the string is decoded as UTF-8. Use the optional encoding parameter can specify a different format.
      • FileReader.readAsDataURL(Blob|File) — The result property will contain the file/blob’s data encoded as a data URL.
      • FileReader.readAsArrayBuffer(Blob|File) — The result property will contain the file/blob’s data as an ArrayBuffer object.

      Once one of these read methods is called on your FileReader object, the onloadstart , onprogress , onload , onabort , onerror , and onloadend events can be used to track its progress.

       

      The example below filters out images from the user’s selection, calls reader.readAsDataURL() on the file, and renders a thumbnail by setting the src attribute to a data URL.

      Example: Reading files. Try it here!

      Slicing a file

      In some cases reading the entire file into memory isn’t the best option. For example, say you wanted to write an asynchronous file uploader. One possible way to speed up the upload would be to read and send the file in separate byte range chunks. The server component would then be responsible for reconstructing the file content in the correct order.

      Luckily for us, the File interface supports a slice method to support this use case. The method takes a starting byte as its first argument, an ending byte as its second, and an optional content type string as a third.

      The following example demonstrates reading chunks of a file. Something worth noting is that it uses the onloadend and checks the evt.target.readyState instead of using the onload event.

      Example: Slicing a file. Try it here!

      Monitoring the progress of a read

      One of the nice things that we get for free when using async event handling is the ability to monitor the progress of the file read; useful for large files, catching errors, and figuring out when a read is complete. The onloadstart and onprogress events can be used to monitor the progress of a read.

      The example below demonstrates displaying a progress bar to monitor the status of a read. To see the progress indicator in action, try a large file or one from a remote drive.

      Example: Monitoring the progress of a read. Try it here!

      Использование файлов в веб приложениях

      Используя File API, добавленный к DOM в HTML5, в веб-приложениях теперь можно запрашивать пользователя выбрать локальные файлы и затем читать содержимое этих файлов. Выбор файлов может осуществляться с помощью элемента <input> или drag and drop.

      Если вы хотите использовать DOM File API в расширениях или коде Chrome, используйте. На самом деле, в таком случае вам необходимо ознакомиться с дополнительными нюансами. См. статью Using the DOM File API in chrome code для подробностей.

      Доступ к выбранным файлам

      Рассмотрим следующий код:

      File API делает возможным доступ к FileList , который содержит объекты File , которым соответствуют файлы, выбранные пользователем.

      Атрибут multiple элемента input позволяет пользователю выбрать несколько файлов.

      Обращение к одному выбранному файлу с использованием классической DOM-модели:

      Обращение к одному выбранному файлу через jQuery:

      Примечание: Ошибка «files is undefined» означает что был выбран не один HTML-элемент, а список элементов, возвращаемый jQuery. Необходимо уточнить, у какого именно элемента требуется вызвать метод «files»

      Доступ к выбранным файлам через событие change

      Также возможно (но не обязательно) получить доступ к FileList через событие change . Нужно использовать EventTarget.addEventListener() чтобы добавить обработчик события change , как показано здесь:

      Обработчик события change можно назначить атрибутом элемента:

      Когда пользователь выбирает файл, функция handleFiles() будет вызвана с объектом FileList , который состоит из объектов File , представляющих файлы, выбранные пользователем.

      Получение информации о выделенных файлах

      Объект FileList предоставляемый классическим DOM содержит все файлы выбранные пользователем, каждый из которых представляет собой объект File . Вы можете определить сколько файлов выбрал пользователь проверяя значение атрибута длины ( length ) списка файлов:

      Конкретные объекты File могут быть получены обращением к списку файлов как к массиву:

      Этот цикл проходит по всем файлам в списке файлов.

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

      Имя файла как строка доступная только для чтения. Это просто имя файла и оно не включает в себя информацию о пути.

      Размер файла в байтах, как 64-битное целое число (возможно только чтение).

      MIME тип файла, как строка доступная только для чтения, или пустая строка ( «» ) если тип файла не может быть определён.

      Пример: Отображение размера файла(ов)

      Следующий пример показывает возможное использование свойства size :

      Использование метода click() скрытых элементов выбора файла

      Начиная с Gecko 2.0, вы можете скрыть непривлекательный элемент <input> и предоставить свой собственный интерфейс для открытия диалогового окна выбора и отображения файла или файлов, выбранных пользователем. Вы можете сделать это, присвоив свойству display элемента input значение none (display:none) и вызывая метод click() скрытого элемента <input> .

      Рассмотрим следующую разметку HTML:

      Код, обрабатывающий событие click, может выглядеть следующим образом:

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

      Использование элемента label скрытого элемента input

      Для того, чтобы открыть диалог выбора файла без использования JavaScript (метода click()), можно воспользоваться элементом <label> .

      Рассмотрим следующую разметку HTML:

      В данном случае нет необходимости добавлять код JavaScript для того, чтобы вызвать fileElem.click() . Также в данном случае вы можете стилизовать элемент label так, как пожелаете.

      Выбор файлов с использованием технологии drag and drop

      Также вы можете предоставить пользователю возможность непосредственно перетаскивать файлы в ваше веб-приложение.

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

      В данном примере мы превращаем элемент с ID, равным dropbox , в нашу зону перетаскивания при помощи добавления обработчиков для событий dragenter , dragover и drop .

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

      Вся настоящая магия происходит в функции drop() :

      Здесь мы извлекаем из события поле dataTransfer , затем вытаскиваем из него список файлов и передаём этот список в handleFiles() . После этого процесс обработки файлов одинаков вне зависимости от того, использовал ли пользователь для их выбора элемент input или технологию drag and drop.

      Пример: Отображение эскизов изображений, выбранных пользователем

      Представим, что вы разрабатываете очередной веб-сайт для обмена фотографиями и вы хотите использовать возможности HTML5 для предварительного просмотра изображений перед тем, как пользователь загрузит их. Вы можете создать input элемент или зону перетаскивания, как обсуждалось ранее, и вызвать такую функцию, как handleFiles() ниже.

      Здесь наш цикл обрабатывает выбранные пользователем файлы, проверяя атрибут type у каждого файла, чтобы определить является ли файл изображением (выполняется регулярное выражение в строке » image.* «). Для каждого файла, который является изображением, мы создаём новый img элемент. Можно использовать CSS для установки красивых рамок, теней, и указания размеров изображения, но здесь нет нужды делать этого.

      Каждое изображение имеет CSS класс obj добавленный к нему для упрощения его поиска в DOM дереве. Мы также добавили атрибут file к каждому изображению, указав File ; это позволит нам получить изображения для фактической загрузки позже. Наконец, мы используем Node.appendChild() для того, чтобы добавить новый эскиз в область предпросмотра нашего документа.

      Затем мы устанавливаем FileReader для обработки асинхронной загрузки изображения и прикрепления его к img элементу. После создания нового объекта FileReader , мы настраиваем его функцию onload , затем вызываем readAsDataURL() для запуска операции чтения в фоновом режиме. Когда всё содержимое файла изображения загружено, они преобразуют его в data: URL, который передаётся в колбэк onload . Наша реализация этой процедуры просто устанавливает атрибут src у элемента img загруженного изображения, в результате чего миниатюра изображения появляется на экране пользователя.

      Использование URLs объектов

      Gecko 2.0 представляет поддержку для методов DOM window.URL.createObjectURL() (en-US) и window.URL.revokeObjectURL() (en-US). Они позволяют создавать простые строки URL, которые могут быть использованы для обращения к любым данным, на которые можно ссылаться, используя объект DOM File , включая локальные файлы на компьютере пользователя.

      Когда у вас есть объект File , на который вы хотите ссылаться по URL из HTML, вы можете создать для этого объект URL, такой как этот:

      URL объекта – это строка, идентифицирующая объект файла File . Каждый раз при вызове window.URL.createObjectURL() (en-US), создаётся новый уникальный объект URL, даже если вы уже создали объект URL для этого файла. Каждый из них должен быть освобождён. В то время как они освобождаются автоматически когда документ выгружается, если ваша страница использует их динамически, вы должны освободить их явно вызовом window.URL.revokeObjectURL() (en-US):

      Пример: Использование URL объектов для отображения изображений

      Этот пример использует URL объектов для отображения эскизов изображений. Кроме этого, оно показывает другую информацию о файлах, включая их имена и размеры. Вы можете посмотреть работающий пример.

      HTML, который представляет интерфейс, выглядит так:

      Здесь определяется элемент файла <input> , а также ссылка, которая вызывает окно выбора файла, т.к. мы сделали элемент ввода файла скрытым, чтобы этот не слишком привлекательный элемент интерфейса не отображался. Об этом рассказывается в разделе Использование метода click() скрытых элементов выбора файла, как о методе вызова окна выбора файла.

      Метод handleFiles() может быть реализован таким образом:

      Он начинается с получения элемента <div> с ID fileList . Это блок, в который мы вставим наш список файлов, включая эскизы..

      Если объект FileList , передаваемый в handleFiles() является null , то мы просто устанавливаем внутренний HTML блока в отображение текста «No files selected!». Иначе мы начинаем строить список файлов таким образом:

      1. Создаётся новый элемент — неупорядоченный список ( <ul> ).
      2. Этот новый элемент вставляется в блок <div> с помощью вызова его метода element.appendChild() .
      3. Для каждого File в FileList , представляемого files :
        1. Создаём новый элемент пункта списка ( <li> ) и вставляем его в список.
        2. Создаём новый элемент изображения ( <img> ).
        3. Устанавливаем источник изображения в новый URL объекта, представляющий файл, используя window.URL.createObjectURL() (en-US) для создания URL на двоичный объект.
        4. Устанавливаем высоту изображения в 60 пикселей.
        5. Устанавливаем обработчик события загрузки изображения для освобождения URL объекта, т.к. после загрузки изображения он больше не нужен. Это делается вызовом метода window.URL.revokeObjectURL() (en-US), передавая в него строку URL объекта, которая указана в img.src .
        6. Добавляем новый элемент в список.

        Пример: Загрузка файла, выбранного пользователем

        Ещё одна вещь, которую вы можете захотеть сделать – это позволить пользователю загрузить выбранный файл или файлы (такие, как изображения из предыдущего примера) на сервер. Это можно сделать асинхронно довольно просто.

        Создание заданий на загрузку

        Продолжая пример с кодом, который строил эскизы в предыдущем примере, напомним, что каждому изображению эскиза присвоен класс CSS class obj , с соответствующим File , прикреплённым в атрибут file . Это позволяет нам очень просто выбрать все изображения, которые пользователь выбрал для загрузки используя Document.querySelectorAll() , как показано здесь:

        Строка 2 получает NodeList в переменную imgs со всеми элементами документа, имеющих класс CSS obj . В нашем случае все они будут эскизами изображений. Как только мы получим этот список, можно просто пройти по нему, создавая для каждого элемента новый экземпляр FileUpload . Каждый из них отвечает за загрузку соответствующего файла.

        Управление процессом загрузки файла

        Функция FileUpload принимает на вход 2 параметра: элемент изображения и файл, из которого нужно читать данные изображения.

        Функция FileUpload() , показанная выше, создаёт объект Throbber, который используется для отображения хода загрузки, а затем создаёт XMLHttpRequest для управления загрузкой данных.

        Перед началом загрузки данных выполняются несколько шагов для подготовки:

        1. На XMLHttpRequest устанавливается обработчик события progress для обновления индикатора хода загрузки новыми значениями процента выполнения, так что по мере хода загрузки, индикатор будет обновляться, отображая последнюю информацию.
        2. На XMLHttpRequest ‘s устанавливается обработчик события load для установки индикатора загрузки в значение 100%, чтобы убедиться, что индикатор действительно установлен в 100% (в случае проблем детализации в ходе процесса). Затем обработчик удаляет индикатор загрузки, т.к. он более не нужен. Поэтому индикатор исчезает как только загрузка завершена.
        3. Запрос на загрузку файла изображения открывается вызовом метода XMLHttpRequest ‘s open() для начала создания POST-запроса.
        4. Тип MIME для загрузки устанавливается вызовом функции XMLHttpRequest overrideMimeType() . В этом случае мы используем общий тип MIME type; вам может быть нужно или не нужно вообще устанавливать тип MIME в зависимости от вашего случая.
        5. Объект FileReader используется для преобразования файла в двоичную строку.
        6. И в завершение, когда содержимое загружено, вызывается функция XMLHttpRequest send() для отправки содержимого файла.

        Асинхронная обработка процесса загрузки

        Пример: Использование URL объектов для отображения PDF

        URL объектов могут быть использованы не только для изображений! Также этот приём можно использовать и для других ресурсов, которые могут отображаться браузером, например, файлы PDF.

        В Firefox, для того чтобы файл PDF появился в iframe и не предлагался для загрузки, нужно установить pdfjs.disabled в значение false Non-standard .

        А здесь изменение атрибута src :

        Пример: Использование URL объектов с другими типами файлов

        Вы можете таким же образом работать с файлами в других форматах. Ниже приведён пример как загружается видео:

         

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *