uploader – Stepan Suvorov Blog https://stepansuvorov.com/blog Release 2.0 Mon, 30 Jul 2012 11:17:21 +0000 en-US hourly 1 https://wordpress.org/?v=6.3.1 Пишем свой Uploader с нуля на javascript используя FileApi. Часть4 https://stepansuvorov.com/blog/2012/07/%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%81%d0%b2%d0%be%d0%b9-uploader-%d1%81-%d0%bd%d1%83%d0%bb%d1%8f-%d0%bd%d0%b0-javascript-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d1%8f-fileapi-%d1%87%d0%b0-4/ https://stepansuvorov.com/blog/2012/07/%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%81%d0%b2%d0%be%d0%b9-uploader-%d1%81-%d0%bd%d1%83%d0%bb%d1%8f-%d0%bd%d0%b0-javascript-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d1%8f-fileapi-%d1%87%d0%b0-4/#respond Mon, 30 Jul 2012 11:17:21 +0000 http://stepansuvorov.com/blog/?p=341 Continue reading ]]> В частях 1, 2, 3 мы научились читать файлы с диска.Теперь попробуем разобрать процесс отправки файлов на сервер с помощью технологии ajax.

В начале вспомним как работать с аяксом для передачи файла на сервер:

  1. Метод передачи будет POST
  2. Обязательно нужно будет указать Content-Type, а именно multipart/form-data
  3. Правильно сформировать само тело сообщения

Получим следующий код(по пунктам):

var request = new XMLHttpRequest(); 
request.onreadystatechange = ajaxReady; 
request.open('POST', 'uploader.php', true); // (1)
request.setRequestHeader('Content-Type', contentType); // (2)
request.sendAsBinary(createTestMsg()); // (3)

ajaxReady – это просто callback-функция, которая вызовется при ajax-ответе. Для нее пока установим простую заглушку:

function ajaxReady() {
    if (request.readyState == 4 && request.status == 200) {
        alert(request.responseText);
    }
}

uploader.php  – тоже пока файл-заглушка на стороне сервера, следующего содержания:

<?php

var_dump($_POST);
var_dump($_FILES);

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

var boundary = "AJAX-----------------------" + (new Date).getTime();
var contentType = "multipart/form-data; boundary=" + boundary;

boundary – это случайная последовательность байт, которые не должны встречаться в самом файле. Вы можете придумать свой алгоритм для генерации данной последовательности, т.к. это лишь пример.

Ну и самое основное – формирование сообщения:

function createTestMsg(){
    var fieldName = 'testfile';
    var fileName  = '4.jpg';
    var CRLF = "\r\n";

    var msg = "--" + boundary + CRLF;
    msg += 'Content-Disposition: form-data; ';
    msg += 'name="' + fieldName + '"; ';
    msg += 'filename="'+ fileName + '"' + CRLF;
    msg += 'Content-Type: application/octet-stream';
    msg += CRLF + CRLF; // marks end of the headers part
    msg += Array(9999).join(7) + CRLF;
    msg += "--" + boundary + "--" + CRLF;
    return msg;
}

Array(9999).join(7) – это такой вариант генерации фэйкового контента для файла.

Вот тут можно посмотреть весь код: http://learn.javascript.ru/play/E1MhM, но в песочнице он работать не будет, т.к. нет файла uploader.php на строне сервера, так что в любом случае нужно копировать локально и смотреть.

]]>
https://stepansuvorov.com/blog/2012/07/%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%81%d0%b2%d0%be%d0%b9-uploader-%d1%81-%d0%bd%d1%83%d0%bb%d1%8f-%d0%bd%d0%b0-javascript-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d1%8f-fileapi-%d1%87%d0%b0-4/feed/ 0
Пишем свой Uploader с нуля на javascript используя FileApi. Часть3 https://stepansuvorov.com/blog/2012/07/%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%81%d0%b2%d0%be%d0%b9-uploader-%d1%81-%d0%bd%d1%83%d0%bb%d1%8f-%d0%bd%d0%b0-javascript-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d1%8f-fileapi-%d1%87%d0%b0-3/ https://stepansuvorov.com/blog/2012/07/%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%81%d0%b2%d0%be%d0%b9-uploader-%d1%81-%d0%bd%d1%83%d0%bb%d1%8f-%d0%bd%d0%b0-javascript-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d1%8f-fileapi-%d1%87%d0%b0-3/#comments Thu, 26 Jul 2012 14:41:46 +0000 http://stepansuvorov.com/blog/?p=261 Continue reading ]]> В этой части мы рассмотрим ключевой момент: чтение файла частями – это очень важно при отправке больших файлов( от 400-700МБ ), т.к. если мы будем пытаться их читать целиком – это вызовет дикие тормоза браузера.

Введем новое определение Blob. Если раньше мы говорили о File, как об объекте всего файла, то Blob – это объект-интерфейс работы с куском файла. Для получения этого объекта необходимо выполнить метод slice для File (в зависимости от браузера это webkitSlice или mozSlice). Думаю мы можем сделать универсальный метод следующим образом:

function fixSlice(file, startingByte, endindByte){
    var blob;
    if (file.webkitSlice) {
        blob = file.webkitSlice(startingByte, endindByte);
    } else if (file.mozSlice) {
        blob = file.mozSlice(startingByte, endindByte);
    }
    return blob;
}

А вот так будет выглядеть код для чтения блоба(мы прочитаем с 0 по 15 байт файла):

document.getElementById('file-field').onchange = function(){
    var file = this.files[0];
    var start = 0;
    var stop = 15;
    var reader = new FileReader;
    reader.onloadend = function(e){
        if (e.target.readyState == FileReader.DONE) {
            document.getElementById('buffer').innerHTML =
             'bytes: ' + start + ' - ' + stop + ' total:' + file.size;
        }
    }
    var blob = fixSlice(file, start, stop);
    reader.readAsBinaryString(blob);
}

Внимание! Тут есть некоторая специфика, по сравнению с чтением объекта File: вместо метода onload используется метод onloadend. И добавилась дополнительная проверка e.target.readyState.

Теперь усложним пример: добавим еще кнопочку чтения  и будем читать файл частями по нажатию этой кнопки:

var file;
var pointer = 0;
var blob_size = 16;
var reader;

document.getElementById('file-field').onchange = function(){
  file = this.files[0];
  reader = new FileReader;
  reader.onloadend = function(e){
    if (e.target.readyState == FileReader.DONE) {
      pointer += blob_size;
      document.getElementById('buffer').innerHTML =
         'bytes: ' + pointer + '/from' + file.size;
    }
  }
}

function doRead(){
  if(window.file){
    var blob = fixSlice(file, pointer, pointer+blob_size);
    reader.readAsBinaryString(blob);
  }else{
    alert('Please select the file');
  }
}

var readbutton = document.getElementById('read-button');
readbutton.addEventListener( "click" , doRead, false);

Как-то так.

pointer - запоминаем текущее положение указателя чтения

Вот тут можно поиграться с текущим кодом: http://learn.javascript.ru/play/yn9Zgb

И еще один вариант с выводом контента файла:  http://learn.javascript.ru/play/qi8olc

Теперь автоматизируем процесс загрузки(не давя на кнопочку): http://learn.javascript.ru/play/K2XUsc

Вот мы и научились загружать файлы по частям используя blob.

]]>
https://stepansuvorov.com/blog/2012/07/%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%81%d0%b2%d0%be%d0%b9-uploader-%d1%81-%d0%bd%d1%83%d0%bb%d1%8f-%d0%bd%d0%b0-javascript-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d1%8f-fileapi-%d1%87%d0%b0-3/feed/ 2
Пишем свой Uploader с нуля на javascript используя FileApi. Часть2 https://stepansuvorov.com/blog/2012/06/%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%81%d0%b2%d0%be%d0%b9-uploader-%d1%81-%d0%bd%d1%83%d0%bb%d1%8f-%d0%bd%d0%b0-javascript-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d1%8f-fileapi-%d1%87%d0%b0-2/ https://stepansuvorov.com/blog/2012/06/%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%81%d0%b2%d0%be%d0%b9-uploader-%d1%81-%d0%bd%d1%83%d0%bb%d1%8f-%d0%bd%d0%b0-javascript-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d1%8f-fileapi-%d1%87%d0%b0-2/#respond Sat, 30 Jun 2012 10:21:10 +0000 http://stepansuvorov.com/blog/?p=255 Continue reading ]]> Вот и созрело продолжение первой части, где мы разобрались как можно использовать родной объект FileReader для чтения файла.

Давайте еще добавим прогресс чтения файла для нашего загрузчика. Для этого зададим callback метод для FileReader:

reader.onprogress = updateProgress;

Рассмотрим что из себя представляет метод updateProgress:

function updateProgress(event) {
    if (event.lengthComputable) {
        var progress = Math.round((event.loaded / event.total) * 100);
        document.getElementById('buffer').innerHTML = progress + '%';
    }
}

Все просто. event.lengthComputable нам необходимо чтобы убедится что event – объект того события, которое мы ждем, а именно ProgressEvent.

Math.round((event.loaded / event.total) * 100)

Примитивная математика для вычисления процента.

document.getElementById('buffer').innerHTML = progress + '%';

Тут мы использовали уже имеющийся textarea элемент с id = buffer, чтобы вывести проценты туда.

Вот что в итоге получилось:  http://learn.javascript.ru/play/u0bbrb
Советую использовать большие файлы( от 100МБ) для проверки работоспособности.

!Внимание: мы рассмотрели пока прогресс загрузки файла локально, т.е. непосредственно чтения содержимого файла скриптом, но еще не саму загрузку данных на сервер.

]]>
https://stepansuvorov.com/blog/2012/06/%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%81%d0%b2%d0%be%d0%b9-uploader-%d1%81-%d0%bd%d1%83%d0%bb%d1%8f-%d0%bd%d0%b0-javascript-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d1%8f-fileapi-%d1%87%d0%b0-2/feed/ 0
Пишем свой Uploader с нуля на javascript используя FileApi. Часть1 https://stepansuvorov.com/blog/2012/04/%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%81%d0%b2%d0%be%d0%b9-uploader-%d1%81-%d0%bd%d1%83%d0%bb%d1%8f-%d0%bd%d0%b0-javascript-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d1%8f-fileapi-%d1%87%d0%b0/ https://stepansuvorov.com/blog/2012/04/%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%81%d0%b2%d0%be%d0%b9-uploader-%d1%81-%d0%bd%d1%83%d0%bb%d1%8f-%d0%bd%d0%b0-javascript-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d1%8f-fileapi-%d1%87%d0%b0/#comments Sun, 29 Apr 2012 12:33:20 +0000 http://stepansuvorov.com/blog/?p=150 Continue reading ]]> Отметим ключевые моменты, которые нас интересуют по FileApi:
– у input с атрибутом type=”file” теперь есть свойство files(массив объектов класса File)
а объект класса File содержит следующие свойства:
name — имя файла
type — MIME тип файла
size — размер в байтах

Для чтения файла мы теперь можем использовать класс FileReader, который имеет следующие методы:
readAsBinaryString(file) — чтение в бинарном режиме.
readAsText(file[, encoding]) — чтение в текстовом режиме. Дополнительным аргументом указывается кодировка (по-умолчанию UTF-8).
readAsDataURL(/forum/file) — чтение в бинарном режиме с последующей перекодировкой в Data:URL.

Основные моменты теории разобрали, остальное – по ходу дела.

Создадим простую HTMLку:

<input type=”file” name=”file” id=”file-field”/>
<textarea id=”buffer”></textarea>

Для наглядности мы не будем сразу отправлять файл, а разберем пошагово процесс и загрузим содержимое файла в тег textarea:

Для этого повесим обработчик изменения состояния на поле ввода файла:

document.getElementById(‘file-field’).onchange = function(){
var reader = new FileReader;
reader.onload = function(e){
document.getElementById(‘buffer’).innerHTML = e.target.result;
}
reader.readAsDataURL(this.files[0]);
}

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

Вот тут можно поиграться с кодом: http://learn.javascript.ru/play/esPXY

Подробнее можно почитать в спецификации: http://www.w3.org/TR/FileAPI/

]]>
https://stepansuvorov.com/blog/2012/04/%d0%bf%d0%b8%d1%88%d0%b5%d0%bc-%d1%81%d0%b2%d0%be%d0%b9-uploader-%d1%81-%d0%bd%d1%83%d0%bb%d1%8f-%d0%bd%d0%b0-javascript-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d1%8f-fileapi-%d1%87%d0%b0/feed/ 3