HTML5 Ajax upload очень больших файлов

// Для начала определим метод XMLHttpRequest.sendAsBinary(),
// если он не определен (Например, для браузера Google Chrome).

if(!XMLHttpRequest.prototype.sendAsBinary){

    XMLHttpRequest.prototype.sendAsBinary=function(datastr){
        function byteValue(x){
            return x.charCodeAt(0)& 0xff;
            }
        var ords = Array.prototype.map.call(datastr, byteValue);
        var ui8a =new Uint8Array(ords);
        this.send(ui8a.buffer);
        }
    }

/**
 * Класс FileUploader.
 * @param ioptions Ассоциативный массив опций загрузки
 */
function FileUploader(ioptions){

    // Позиция, с которой будем загружать файл
    this.position=0;

    // Размер загружаемого файла
    this.filesize=0;

    // Объект Blob или File (FileList[i])
    this.file=null;

    // Ассоциативный массив опций
    this.options=ioptions;

    // Если не определена опция uploadscript, то возвращаем null. Нельзя
    // продолжать, если эта опция не определена.
    if(this.options[‘uploadscript’]==undefined)returnnull;

    /*
    * Проверка, поддерживает ли браузер необходимые объекты
    * @return true, если браузер поддерживает все необходимые объекты
    */
    this.CheckBrowser=function(){
        if(window.File&& window.FileReader&& window.FileList&& window.Blob)returntrue;elsereturnfalse;
        }

    /*
    * Загрузка части файла на сервер
    * @param from Позиция, с которой будем загружать файл
    */
    this.UploadPortion=function(from){

        // Объект FileReader, в него будем считывать часть загружаемого файла
        var reader =new FileReader();

        // Текущий объект
        var that=this;

        // Позиция с которой будем загружать файл
        var loadfrom=from;

        // Объект Blob, для частичного считывания файла
        var blob=null;

        // Таймаут для функции setTimeout. С помощью этой функции реализована повторная попытка загрузки
        // по таймауту (что не совсем корректно)
        var xhrHttpTimeout=null;

        /*
        * Событие срабатывающее после чтения части файла в FileReader
        * @param evt Событие
        */
        reader.onloadend=function(evt){
            if(evt.target.readyState== FileReader.DONE){

                // Создадим объект XMLHttpRequest, установим адрес скрипта для POST
                // и необходимые заголовки HTTP запроса.
                var xhr =new XMLHttpRequest();
                xhr.open(‘POST’, that.options[‘uploadscript’],true);
                xhr.setRequestHeader(«Content-Type»,»application/x-binary; charset=x-user-defined»);

                // Идентификатор загрузки (чтобы знать на стороне сервера что с чем склеивать)
                xhr.setRequestHeader(«Upload-Id», that.options[‘uploadid’]);
                // Позиция начала в файле
                xhr.setRequestHeader(«Portion-From», from);
                // Размер порции
                xhr.setRequestHeader(«Portion-Size», that.options[‘portion’]);

                // Установим таймаут
                that.xhrHttpTimeout=setTimeout(function(){
                    xhr.abort();
                    },that.options[‘timeout’]);

                /*
                * Событие XMLHttpRequest.onProcess. Отрисовка ProgressBar.
                * @param evt Событие
                */
                xhr.upload.addEventListener(«progress»,function(evt){
                    if(evt.lengthComputable){

                        // Посчитаем количество закаченного в процентах (с точность до 0.1)
                        var percentComplete = Math.round((loadfrom+evt.loaded)*1000/ that.filesize);percentComplete/=10;
           
                        // Посчитаем ширину синей полоски ProgressBar
                        var width=Math.round((loadfrom+evt.loaded)*300/ that.filesize);

                        // Изменим свойства элементом ProgressBar’а, добавим к нему текст
                        var div1=document.getElementById(‘cnuploader_progressbar’);
                        var div2=document.getElementById(‘cnuploader_progresscomplete’);

                        div1.style.display=’block’;
                        div2.style.display=’block’;
                        div2.style.width=width+’px’;
                        if(percentComplete<30){
                            div2.textContent=»;
                            div1.textContent=percentComplete+’%’;
                            }
                        else{
                            div2.textContent=percentComplete+’%’;
                            div1.textContent=»;
                            }
                        }
                   
                    },false);

                /*
                * Событие XMLHttpRequest.onLoad. Окончание загрузки порции.
                * @param evt Событие
                */
                xhr.addEventListener(«load»,function(evt){

                    // Очистим таймаут
                    clearTimeout(that.xhrHttpTimeout);

                    // Если сервер не вернул HTTP статус 200, то выведем окно с сообщением сервера.
                    if(evt.target.status!=200){
                        alert(evt.target.responseText);
                        return;
                        }

                    // Добавим к текущей позиции размер порции.
                    that.position+=that.options[‘portion’];

                    // Закачаем следующую порцию, если файл еще не кончился.
                    if(that.filesize>that.position){
                        that.UploadPortion(that.position);
                        }
                    else{
                        // Если все порции загружены, сообщим об этом серверу. XMLHttpRequest, метод GET,
                        // PHP скрипт тот-же.
                        var gxhr =new XMLHttpRequest();
                        gxhr.open(‘GET’, that.options[‘uploadscript’]+’?action=done’,true);

                        // Установим идентификатор загруки.
                        gxhr.setRequestHeader(«Upload-Id», that.options[‘uploadid’]);

                        /*
                        * Событие XMLHttpRequest.onLoad. Окончание загрузки сообщения об окончании загрузки файла :).
                        * @param evt Событие
                        */
                        gxhr.addEventListener(«load»,function(evt){

                            // Если сервер не вернул HTTP статус 200, то выведем окно с сообщением сервера.
                            if(evt.target.status!=200){
                                alert(evt.target.responseText.toString());
                                return;
                                }
                            // Если все нормально, то отправим пользователя дальше. Там может быть сообщение
                            // об успешной загрузке или следующий шаг формы с дополнительным полями.
                            else window.parent.location=that.options[‘redirect_success’];
                            },false);

                        // Отправим HTTP GET запрос
                        gxhr.sendAsBinary(»);
                        }
                    },false);

                /*
                * Событие XMLHttpRequest.onError. Ошибка при загрузке
                * @param evt Событие
                */
                xhr.addEventListener(«error»,function(evt){

                    // Очистим таймаут
                    clearTimeout(that.xhrHttpTimeout);

                    // Сообщим серверу об ошибке во время загруке, сервер сможет удалить уже загруженные части.
                    // XMLHttpRequest, метод GET,  PHP скрипт тот-же.
                    var gxhr =new XMLHttpRequest();

                    gxhr.open(‘GET’, that.options[‘uploadscript’]+’?action=abort’,true);

                    // Установим идентификатор загруки.
                    gxhr.setRequestHeader(«Upload-Id», that.options[‘uploadid’]);

                    /*
                    * Событие XMLHttpRequest.onLoad. Окончание загрузки сообщения об ошибке загрузки :).
                    * @param evt Событие
                    */
                    gxhr.addEventListener(«load»,function(evt){

                        // Если сервер не вернул HTTP статус 200, то выведем окно с сообщением сервера.
                        if(evt.target.status!=200){
                            alert(evt.target.responseText);
                            return;
                            }
                        },false);

                    // Отправим HTTP GET запрос
                    gxhr.sendAsBinary(»);

                    // Отобразим сообщение об ошибке
                    if(that.options[‘message_error’]==undefined)alert(«There was an error attempting to upload the file.»);elsealert(that.options[‘message_error’]);
                    },false);

                /*
                * Событие XMLHttpRequest.onAbort. Если по какой-то причине передача прервана, повторим попытку.
                * @param evt Событие
                */
                xhr.addEventListener(«abort»,function(evt){
                    clearTimeout(that.xhrHttpTimeout);
                    that.UploadPortion(that.position);
                    },false);

                // Отправим порцию методом POST
                xhr.sendAsBinary(evt.target.result);
                }
            };

        that.blob=null;

        // Считаем порцию в объект Blob. Три условия для трех возможных определений Blob.[.*]slice().
        if(this.file.slice) that.blob=this.file.slice(from,from+that.options[‘portion’]);
        else{
            if(this.file.webkitSlice) that.blob=this.file.webkitSlice(from,from+that.options[‘portion’]);
            else{
                if(this.file.mozSlice) that.blob=this.file.mozSlice(from,from+that.options[‘portion’]);
                }
            }

        // Считаем Blob (часть файла) в FileReader
        reader.readAsBinaryString(that.blob);
        }

    /*
    * Загрузка файла на сервер
    * return Число. Если не 0, то произошла ошибка
    */
    this.Upload=function(){

        // Скроем форму, чтобы пользователь не отправил файл дважды
        var e=document.getElementById(this.options[‘form’]);
        if(e) e.style.display=’none’;

        if(!this.file)return-1;
        else{

            // Если размер файла больше размера порциии ограничимся одной порцией
            if(this.filesize>this.options[‘portion’])this.UploadPortion(0,this.options[‘portion’]);

            // Иначе отправим файл целиком
            elsethis.UploadPortion(0,this.filesize);
            }
        }

    if(this.CheckBrowser()){

        // Установим значения по умолчанию
        if(this.options[‘portion’]==undefined)this.options[‘portion’]=1048576;
        if(this.options[‘timeout’]==undefined)this.options[‘timeout’]=15000;

        var that =this;

        // Добавим обработку события выбора файла
        document.getElementById(this.options[‘formfiles’]).addEventListener(‘change’,function(evt){

            var files=evt.target.files;

            // Выберем только первый файл
            for(var i =0, f; f = files[i]; i++){
                that.filesize=f.size;
                that.file= f;
                break;
                }
            },false);

        // Добавим обработку события onSubmit формы
        document.getElementById(this.options[‘form’]).addEventListener(‘submit’,function(evt){
            that.Upload();
            (arguments[0].preventDefault)? arguments[0].preventDefault(): arguments[0].returnValue=false;
            },false);
        }

    }

Источник: http://feedproxy.google.com/~r/codenet/read/~3/bc8ezTzpUio/

Источник: lred.ru

Оцените статью
новости для мужчин