Новости
- Вступ
- вибір файлів
- Вибір файлів за допомогою форми введення даних
- Вибір файлів за допомогою перетягування
- читання файлів
- Поділ файлу на фрагменти
- Контроль ходу читання
Вступ
Нарешті з'явилася можливість взаємодії з локальними файлами за допомогою HTML5. Для цього служить специфікація API файлів . Зокрема, API файлів можна використовувати для створення зменшених зображень при передачі відповідних картинок на сервер або для того, щоб додаток могло зберегти посилання на файл, якщо користувача немає в мережі. Крім того, за допомогою коду на стороні клієнта можна перевірити, чи відповідає тип MIME завантаження його розширення, або встановити обмеження за розміром.
У специфікації зазначені деякі інтерфейси для доступу до файлів в локальній файловій системі.
- File - окремий файл. Така інформація, як назва, розмір файлу, тип MIME і посилання на оброблювач, доступна тільки для читання.
- FileList - послідовність об'єктів File у вигляді масиву, що дозволяє, наприклад, реалізувати функцію <input type = "file" multiple> або перетягування папки з файлами з робочого столу.
- Blob - дозволяє розділити файл на фрагменти заданої величини.
У поєднанні з описаними вище структурами даних інтерфейс FileReader можна використовувати для асинхронного читання файлу за допомогою знайомих функцій обробки подій в JavaScript. Це дозволяє відстежувати процес читання, виявляти помилки і визначати, що завантаження завершено. API багато в чому нагадують модель подій XMLHttpRequest.
Примітка. На момент складання цього керівництва API, необхідні для роботи з локальними файлами, підтримувалися в браузерах Chrome 6.0 і Firefox 3.6. Починаючи з версії Firefox 3.6.3 метод File.slice () не підтримується.
вибір файлів
Спочатку перевірте, чи підтримує ваш браузер API файлів.
// Check for the various File API support. if (window.File && window.FileReader && window.FileList && window.Blob) {// Great success! All the File APIs are supported. } Else {alert ( 'The File APIs are not fully supported in this browser.'); }Зрозуміло, якщо для роботи додатка потрібні лише деякі з цих API, скоректуйте фрагмент коду відповідним чином.
Вибір файлів за допомогою форми введення даних
Найпростіший спосіб завантаження файлів - використання стандартного елемента <input type = "file">. JavaScript повертає список обраних об'єктів File у вигляді об'єкта FileList. Ось приклад використання атрибута multiple для вибору відразу декількох файлів:
<Input type = "file" id = "files" name = "files []" multiple /> <output id = "list"> </ output> <script> function handleFileSelect (evt) {var files = evt.target. files; // FileList object // files is a FileList of File objects. List some properties. var output = []; for (var i = 0, f; f = files [i]; i ++) {output.push ( '<li> <strong>', escape (f.name), '</ strong> (', f.type || 'n / a', ') -', f.size, 'bytes, last modified:', f.lastModifiedDate.toLocaleDateString (), '</ li>'); } Document.getElementById ( 'list'). InnerHTML = '<ul>' + output.join ( '') + '</ ul>'; } Document.getElementById ( 'files'). AddEventListener ( 'change', handleFileSelect, false); </ Script>Приклад: вибір файлів за допомогою форми введення даних. Спробуйте самі!
Вибір файлів за допомогою перетягування
Ще одним способом завантаження файлів є їх перетягування з робочого столу в браузер. Щоб включити підтримку перетягування, досить внести невеликі зміни в код з попереднього прикладу.
<Div id = "drop_zone"> Drop files here </ div> <output id = "list"> </ output> <script> function handleFileSelect (evt) {evt.stopPropagation (); evt.preventDefault (); var files = evt.dataTransfer.files; // FileList object. // files is a FileList of File objects. List some properties. var output = []; for (var i = 0, f; f = files [i]; i ++) {output.push ( '<li> <strong>', escape (f.name), '</ strong> (', f.type || 'n / a', ') -', f.size, 'bytes, last modified:', f.lastModifiedDate.toLocaleDateString (), '</ li>'); } Document.getElementById ( 'list'). InnerHTML = '<ul>' + output.join ( '') + '</ ul>'; } Function handleDragOver (evt) {evt.stopPropagation (); evt.preventDefault (); evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy. } // Setup the dnd listeners. var dropZone = document.getElementById ( 'drop_zone'); dropZone.addEventListener ( 'dragover', handleDragOver, false); dropZone.addEventListener ( 'drop', handleFileSelect, false); </ Script>Приклад: вибір файлів за допомогою перетягування. Спробуйте самі!
Перетягніть сюди файли
Примітка. Деякі браузери обробляють елементи <input type = "file"> як цільові області для перетягування файлів. Спробуйте перетягнути файли в поле введення в попередньому прикладі.
читання файлів
А тепер найцікавіше.
Отримавши посилання на об'єкт File, створіть екземпляр об'єкта FileReader , Який збереже його зміст в пам'ять. Як тільки завершується завантаження, на стороні користувача викликається подія onload. Його атрибут result можна використовувати для доступу до даних у файлі.
Існує чотири методи асинхронного читання файлів за допомогою об'єкта FileReader.
- FileReader.readAsBinaryString (Blob | File) - властивість result містить дані про файлі або його фрагменті у вигляді рядка бінарного коду. Кожен байт представлений цілим числом від 0 до 255.
- FileReader.readAsText (Blob | File, opt_encoding) - властивість result містить дані про файлі або його фрагменті у вигляді текстового рядка. За замовчуванням використовується кодування UTF-8. Щоб задати інший формат, використовуйте необов'язковий параметр кодування opt_encoding.
- FileReader.readAsDataURL (Blob | File) - властивість result містить дані про файлі або його фрагменті у вигляді схеми data: URL .
- FileReader.readAsArrayBuffer (Blob | File) - властивість result містить дані про файлі або його фрагменті у вигляді об'єкта ArrayBuffer .
Якщо для об'єкта FileReader викликається один з цих методів, то хід його обробки можна відстежувати за допомогою атрибутів onloadstart, onprogress, onload, onabort, onerror і onloadend.
У прикладі нижче з виділених користувачем файлів вибираються картинки, викликається функція reader.readAsDataURL () і виводиться зменшене зображення шляхом установки для атрибута src значення, що представляє URL даних.
<Style> .thumb {height: 75px; border: 1px solid # 000; margin: 10px 5px 0 0; } </ Style> <input type = "file" id = "files" name = "files []" multiple /> <output id = "list"> </ output> <script> function handleFileSelect (evt) {var files = evt.target.files; // FileList object // Loop through the FileList and render image files as thumbnails. for (var i = 0, f; f = files [i]; i ++) {// Only process image files. if (! f.type.match ( 'image. *')) {continue; } Var reader = new FileReader (); // Closure to capture the file information. reader.onload = (function (theFile) {return function (e) {// Render thumbnail. var span = document.createElement ( 'span'); span.innerHTML = [ '<img class = "thumb" src = "' , e.target.result, ' "title ="', escape (theFile.name), ' "/>']. join ( ''); document.getElementById ( 'list'). insertBefore (span, null); };}) (f); // Read in the image file as a data URL. reader.readAsDataURL (f); }} Document.getElementById ( 'files'). AddEventListener ( 'change', handleFileSelect, false); </ Script>Приклад: читання файлів. Спробуйте самі!
Поділ файлу на фрагменти
У деяких випадках зчитування всього файлу в пам'ять не є оптимальним варіантом. Припустимо, ви вирішили створити інструмент для асинхронної завантаження файлів. Щоб збільшити її швидкість, можна розділити файл на фрагменти однакового розміру, які будуть зчитуватися і відправлятися окремо. На сервері фрагменти будуть знову об'єднуватися в потрібному порядку.
Інтерфейс File підтримує метод slice для розбиття файлу на фрагменти. Першим аргументом цього методу є початковий байт файлу, другим - його останній байт, а третім - необов'язковий ланцюжок з описом типу змісту. Семантика цього методу недавно була змінена, і тепер необхідно використовувати префікс браузера:
if (file.webkitSlice) {var blob = file.webkitSlice (startingByte, endindByte); } Else if (file.mozSlice) {var blob = file.mozSlice (startingByte, endindByte); } Reader.readAsBinaryString (blob);Нижче представлений код для зчитування фрагментів файлу. Зверніть увагу на те, що на місці події onload в ньому використовується подія onloadend, а також перевіряється умова evt.target.readyState.
<Style> #byte_content {margin: 5px 0; max-height: 100px; overflow-y: auto; overflow-x: hidden; } #Byte_range {margin-top: 5px; } </ Style> <input type = "file" id = "files" name = "file" /> Read bytes: <span class = "readBytesButtons"> <button data-startbyte = "0" data-endbyte = "4 "> 1-5 </ button> <button data-startbyte =" 5 "data-endbyte =" 14 "> 6-15 </ button> <button data-startbyte =" 6 "data-endbyte =" 7 "> 7-8 </ button> <button> entire file </ button> </ span> <div id = "byte_range"> </ div> <div id = "byte_content"> </ div> <script> function readBlob ( opt_startByte, opt_stopByte) {var files = document.getElementById ( 'files'). files; if (! files.length) {alert ( 'Please select a file!'); return; } Var file = files [0]; var start = parseInt (opt_startByte) || 0; var stop = parseInt (opt_stopByte) || file.size - 1; var reader = new FileReader (); // If we use onloadend, we need to check the readyState. reader.onloadend = function (evt) {if (evt.target.readyState == FileReader.DONE) {// DONE == 2 document.getElementById ( 'byte_content'). textContent = evt.target.result; document.getElementById ( 'byte_range'). textContent = [ 'Read bytes:', start + 1, '-', stop + 1, 'of', file.size, 'byte file']. join ( ''); }}; if (file.webkitSlice) {var blob = file.webkitSlice (start, stop + 1); } Else if (file.mozSlice) {var blob = file.mozSlice (start, stop + 1); } Reader.readAsBinaryString (blob); } Document.querySelector ( '. ReadBytesButtons'). AddEventListener ( 'click', function (evt) {if (evt.target.tagName.toLowerCase () == 'button') {var startByte = evt.target.getAttribute ( ' data-startbyte '); var endByte = evt.target.getAttribute (' data-endbyte '); readBlob (startByte, endByte);}}, false); </ Script>Приклад: поділ файлу на фрагменти. Спробуйте самі!
Контроль ходу читання
Одним з переваг асинхронної обробки подій є можливість відслідковувати хід читання: це особливо зручно при роботі з великими файлами, для контролю помилок і для визначення моменту завершення читання.
Хід читання можна відстежувати за допомогою подій onloadstart і onprogress.
Нижче наведено код, що відображає рядок ходу читання. Щоб оцінити його в дії, завантажте файл, який має великий розмір або знаходиться на віддаленому носії.
<Style> #progress_bar {margin: 10px 0; padding: 3px; border: 1px solid # 000; font-size: 14px; clear: both; opacity: 0; -moz-transition: opacity 1s linear; -o-transition: opacity 1s linear; -webkit-transition: opacity 1s linear; } # Progress_bar.loading {opacity: 1.0; } #Progress_bar .percent {background-color: # 99ccff; height: auto; width: 0; } </ Style> <input type = "file" id = "files" name = "file" /> <button onclick = "abortRead ();"> Cancel read </ button> <div id = "progress_bar"> < div class = "percent"> 0% </ div> </ div> <script> var reader; var progress = document.querySelector ( '. percent'); function abortRead () {reader.abort (); } Function errorHandler (evt) {switch (evt.target.error.code) {case evt.target.error.NOT_FOUND_ERR: alert ( 'File Not Found!'); break; case evt.target.error.NOT_READABLE_ERR: alert ( 'File is not readable'); break; case evt.target.error.ABORT_ERR: break; // noop default: alert ( 'An error occurred reading this file.'); }; } Function updateProgress (evt) {// evt is an ProgressEvent. if (evt.lengthComputable) {var percentLoaded = Math.round ((evt.loaded / evt.total) * 100); // Increase the progress bar length. if (percentLoaded <100) {progress.style.width = percentLoaded + '%'; progress.textContent = percentLoaded + '%'; }}} Function handleFileSelect (evt) {// Reset progress indicator on new file selection. progress.style.width = '0%'; progress.textContent = '0%'; reader = new FileReader (); reader.onerror = errorHandler; reader.onprogress = updateProgress; reader.onabort = function (e) {alert ( 'File read cancelled'); }; reader.onloadstart = function (e) {document.getElementById ( 'progress_bar'). className = 'loading'; }; reader.onload = function (e) {// Ensure that the progress bar displays 100% at the end. progress.style.width = '100%'; progress.textContent = '100%'; setTimeout ( "document.getElementById ( 'progress_bar'). className = '';", 2000); } // Read in the image file as a binary string. reader.readAsBinaryString (evt.target.files [0]); } Document.getElementById ( 'files'). AddEventListener ( 'change', handleFileSelect, false); </ Script>Приклад: відстеження ходу читання. Спробуйте самі!