При всем бурном развитии web, и стандартов html в частности, работа  с файлами, практически никогда не менялась. К счастью, с приходом HTML5 и связанных с ним API, сейчас у нас гораздо больше возможностей для работы с файлами, чем когда-либо в предыдущих версиях браузеров(iOS до сих пор нет поддержки File API).

Тип Файл - File

Тип File определен в спецификации File API[1] и является абстрактным представлением файла. Каждый экземпляр File имеет следующие свойства:
 name – имя файла
 size – размер файла в байтах
 type –  MIME тип файла

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

Получение ссылок на файлы

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

 Когда вы используете элемент <input type="file">, Вы даете веб странице (и серверу) разрешение на доступ к файлу.  Так, что первое, как вы можете получить объект File, это поле <input type="file">.

HTML5 определяет файловые ссылки для всех <input type="file"> управления. Эта коллекция FileList, которая представляет собой структуру в виде массива под названием FileList содержащую объекты типа File для каждого выбранного файла в поле <input type="file">  (помните, HTML5 позволяет выбрать несколько файлов в этом элементе управления). Так что в любой момент времени, Вы можете получить доступ к файлам пользователя, которые он  выбрал, с помощью кода вроде этого:

<input type="file" id="your-files" multiple>

и

<script>
var control = document.getElementById("your-files");
control.addEventListener("change", function(event) {
    // Когда происходит изменение элементов управления, значит появились новые файлы
    var i = 0,
        files = control.files,
        len = files.length;

    for (; i < len; i++) {
        console.log("Filename: " + files[i].name);
        console.log("Type: " + files[i].type);
        console.log("Size: " + files[i].size + " bytes");
    }

}, false);
</script>

Этот сравнительно простой код ожидает событие изменения в контроле(<input type="file"> ). Когда событие происходит, это означает, что выбор файла изменился, и код перебирает все объекты типа File и выводит информацию из них. Имейте в виду, что свойство файлов всегда доступны из JavaScript, так что вам не придется ждать следующего изменения, чтобы попытаться сделать что-то другое с ними.

Drag and drop файлов

Доступ к файлам из формы по средствам контролов по-прежнему требует действий пользователей: нахождение и выбора  интересующего файла. К счастью, HTML5 Drag and Drop  предоставляет еще один способ для пользователей, чтобы предоставить доступ к своим файлам: путем простого перетаскивания файлов с рабочего стола в веб-браузер. Все, что вам нужно сделать, чтобы это реализовать отслеживать два события.

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

<div id="your-files"></div>
<script>
var target = document.getElementById("your-files");
target.addEventListener("dragover", function(event) {
    event.preventDefault(); // отменяем действие по умолчанию
}, false);
target.addEventListener("drop", function(event) {
    // отменяем действие по умолчанию
    event.preventDefault();
    var i = 0,
     files = event.dataTransfer.files,
     len = files.length;
     for (; i < len; i++) {
          console.log("Filename: " + files[i].name);
          console.log("Type: " + files[i].type);
          console.log("Size: " + files[i].size + " bytes");
     }
}, false);
</script>

event.dataTransfer.files другой FileList объект, через который вы можете получить доступ, к информации о файлах. Код почти такой же, как и контролами формы и объекты типа File могут быть доступны таким же образом.

AJAX pагрузка файлов

Если у вас есть ссылка на файл, то вы сможете сделать очень удобную вещь: загрузить файл с помощью Ajax. Все это возможно благодаря объекту FormData, которая определен в XMLHttpRequest . Этот объект представляет собой HTML-форму и позволяет добавлять пары ключ-значение, которые будут переданы на сервер с помощью метода append():

var form = new FormData();
form.append("name", "Николай");

Самое замечательное в объекте FormData, что вы можете добавить файл непосредственно к нему, фактически имитируя загрузку файла через HTML-форму. Все, что вам нужно сделать, это добавить в файл ссылки с определенным именем, и браузер сделает все остальное. Для примера:

// Создаем форму с несколькими значениями
var form = new FormData();
form.append("name", "Николай");
form.append("photo", control.files[0]);

// отправляем через xhr
var xhr = new XMLHttpRequest();
xhr.onload = function() {
    console.log("Отправка завершена");
};
xhr.open("post", "/entrypoint", true);
xhr.send(form);

Как только объект FormData передается в send (), надлежащие к его содержимому HTTP заголовки  устанавливаются автоматически. Вам не нужно беспокоиться об установке правильной кодировки формы при использовании файлов, сервер будет работать с полученными файлами, так как если бы  была отправлена​​ обычная HTML форма , читая данные о присланном файле из $_FILES['photo'] и текстовыt данных из $_POST['name']. Это дает вам универсальность, чтобы написать код обработки на стороне сервера, который может легко работать как с традиционными HTML-формами так и с формами присланными через Ajax.

И все это работает на последней версии большинства браузеров, включая Internet Explorer 10. К сожалению Internet Explorer 9 этого пока не поддерживает. 

Что дальше

Теперь вы знаете два способа доступа к информации о файле в браузере: через контрол формы и через нативный 'drag and drop'. Вероятно, появятся и другие способы доступа к файлам в будущем, но сейчас Вам нужно знать только эти два. Конечно, читать информацию о файлах, это только часть проблемы.Следующим шагом будет чтение  данных из этих файлов, об этом и напишу во второй части статьи.

Ссылки по теме:

File API спецификация

HTML5 Drag and Drop

XMLHttpRequest Level 2

 

Связанные статьи

Работа с файлами в JavaScript, Часть 2: FileReader
Работа с файлами в JavaScript, Часть 3:Событие прогресса и ошибки
Работа с файлами в JavaScript, Часть 4:Объект URL

Оригинал статьи: http://www.nczonline.net/blog/2012/05/08/working-with-files-in-javascript-part-1/

Рассказать друзьям
author.jpg

Платная консультация по вопросам 2500 руб/час

Прочитали статью и остались вопросы? Меня зовут Валерий и я её автор. С радостью объясню Вам в скайпе все затруднительные моменты, которые остались за рамками статьи!

Подробнее ...

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


Комментарии   

Vldimir
+3 # Vldimir 06.06.2013 08:30
Это всё замечательно, но НИКАК не работатет в IE8!!!
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Skoder
+8 # Skoder 06.06.2013 17:18
в топку все устаревшие браузеры, они тянут веб вниз
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Элчин
+9 # Элчин 22.10.2017 18:00
Привет Вам с 2017! IE8 умер!
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Andrej
0 # Andrej 08.08.2013 20:25
а такой глупый вопрос, а как javascript вынести в отдельный файл?
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
dlipov
+3 # dlipov 28.08.2013 19:29
просто выносишь его в другой файл, а на нужной странице подключаешь через html тег:

<script type="text/javascript" src="tvoi_fail.js"></script>


и вызываешь уже нужные функции в коде.
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Саныч
+2 # Саныч 12.10.2013 04:15
Большое спасибо вам! Я теперь понял принцип отправки файл через ajax. Огромное вам спасибо!
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Roma-IT
+4 # Roma-IT 15.01.2014 19:23
Спасибо за лаконичность — это одно из лучших руководств, которые я нашел. Разве, что drag'n'drop я бы поставил в самом конце статьи.



Кстати, у вас крайне сложно оставить комментарий из-за странных ограничений на имя пользователя.
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
guundu
+2 # guundu 03.11.2014 18:50
new FormData();

Нужно выбранный txt загрузить на сервер и по событию окончания загрузки сразу же и вывести на той же ajax странице в div.



<input type="file>



Проблема с обработчиком php.

Этот "дежурный вариант" работает для обычных форм - и есть зародыш моих знаний:

<?php

move_uploaded_file($_FILES["filename"]["tmp_name"], "./".$_FILES["filename"]["name"]);

?>



Пожалуйста помогите - данного решения видимо нету, все статьи один в один про прогресс-барз.

Мне надо ивент загрузки "on upload" файла на сервер.

if (move... ){

file_get_contents("./".$_FILES["filename"]["name"]);

}

Насколько понимаю - где-то так?



В какой-то статье в Интернет я читал, что можно submit убирать. Но если даже и использовать onsubmit, то этот ивент происходит на клиентской стороне.

И вообще минимальная реализация, txt -> [div] прямо по выбору в <input type="file"> - не должна быть длинная?

Вы как - видите решение?



<div id="iiii"> </div>

<form id="f">

<input type="file" name="filename">

</form>

<script>

var fd=new FormData(document.getElementById("f"));

j=new XMLHttpRequest();

j.open("POST", "upld.php",true);

j.send(f);

j.onreadystatechange=function(){document.getElementById("iiii").textContent=j.responseText;}

</script>
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Кирилл Кулеш
+2 # Кирилл Кулеш 05.02.2016 00:26
Отличная статья!
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Adamastor
+2 # Adamastor 12.06.2016 16:57
Здравствуйте уважаемые посетители сайта!

Никак не могу сохранить бинарные данные на стороне своего сервера. Не могу понять как их правильно извлечь в PHP скрипте, или, возможно, дело в чем-то другом о чем я не догадываюсь. Пробовал бинарные данные упаковывать в контейнер Blob, может попробовать в ArrayBuffer? Методом POST на сервер отсылается объект 'Blob' или 'ArrayBuffer', может надо обратится к каким-либо его свойтвам дабы извлечь данные?

Суть схемы в том чтобы с помощью XHR запроса получить аудио файл в формате MP3 и в последствии записать (спарсить) его себе на сервер.

Ссылка на файл с JS и PHP скриптами: http://file.sampo.ru/2rjjsf/

Помогите пожалуйста!

Зарание благодарен! С уважением, Олег.
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
PROPHESSOR
-1 # PROPHESSOR 24.07.2017 17:28
AJAX pагрузка файлов
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Hemstädning göteborg
0 # Hemstädning göteborg 31.07.2021 07:01
І merely wantеd too thаnk yοu once аgain for уour amazing blog you have creatеd herе.
Its full off useful tips foг those who are truly іnterested inn tthis knd ᧐f
subject, ρarticularly thіs veгy post. Yourr
ɑll ɑbsolutely sweet аnd alsο thougghtful of otheгs and reading
youг sikte posts is a wonderful deligght tо me. Ꭺnd thats a generous treat!
Tom and I ѡill hɑve enjoyment maкing use
of үour idewas in what we ѕhould insteaɗ do in a
few weeкs. Oսr record is a ditance lⲟng and simply pᥙt tips wiⅼl bbe pսt to fine use.
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору