При всем бурном развитии 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/

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

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


Защитный код
Обновить

Комментарии   

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

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


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



Кстати, у вас крайне сложно оставить комментарий из-за странных ограничений на имя пользователя.
0
guundu
# 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>
0
Кирилл Кулеш
# Кирилл Кулеш 05.02.2016 00:26
Отличная статья!
0
Adamastor
# Adamastor 12.06.2016 16:57
Здравствуйте уважаемые посетители сайта!

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

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

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

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

Зарание благодарен! С уважением, Олег.