Подтвердить что ты не робот

Можно ли загружать файл только через $.ajax(параметры) или xhr.send(файл)?

Я использую файлы api и xhr2 spec. Я создал загрузчик (поддерживаемый flash для старых браузеров), который использовал FormData и $.ajax(options), где объект FormData с File был частью объекта options.data. Все работало.

Теперь я решил удалить FormData из-за слабой поддержки браузера. И я не могу понять, как загрузить файл, кроме

var xhr = new XMLHttpRequest();
xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.setRequestHeader("X-File-Name", file.name);
xhr.send(file);

Это не возвращает обещание, которое я могу использовать в функции рекурсии.

Мой код выглядит так:

   startUpload: function() {
        var that = this;
        that.recurseSend(that.queue);       
    },

    _initProgressListener: function (options, file) {
        var that = this;
        var xhr = $.ajaxSettings.xhr();
        options.contentType = 'multipart/form-data';        
        options.processData = false;
        options.type = 'POST';
        // WHAT TO DO HERE TO avoid FormData???? What ever I put into options.data - fails

        /* THIS WOULD WORK
        var formData = new FormData();
        formData.append('file', file);
        options.data = formData;
        */            

        if (xhr.upload && xhr.upload.addEventListener) {
            xhr.upload.addEventListener('progress', function (e) {
                that._onProgress(e, file);
            }, false);
            options.xhr = function () {
                return xhr;
            };
        }
    }, 

    recurseSend: function (queue) { 
        var file = queue.pop();
        if(file != undefined) {
            var that = this;
            var options = that.options;    
            that._initProgressListener(options, file);

            var send = function() {
                jqXHR = ($.ajax(options)).done(function(result, textStatus, jqXHR) {
                        that._onDone(result, textStatus, jqXHR, file);
                        queue.stats['successful_uploads']++;
                    }).fail(function(jqXHR, textStatus, errorThrown) {
                        that._onFail(jqXHR, textStatus, errorThrown, file);
                        queue.stats['upload_errors']++;
                    }).always(function(result, textStatus, jqXHR) {
                        that._onAlways(result, textStatus, jqXHR, file);
                        queue.stats['files_queued']--;
                        that.recurseSend(queue);
                    });
                    return jqXHR;
            };

            this._beforeSend(file);              
            return send();
        }
    },

Чтобы сделать его коротким, $.ajax(options) разрешается в xhr.send(formData), если options.data = FormData, но как я могу его разрешить в xhr.send(file)?

EDITED: я играл с ним, и если я устанавливаю options.data = file; то $.ajax(options) выполняет xhr.send(theFile); но с ошибкой Error: INVALID_STATE_ERR: DOM Exception 11

и запрос отправляется как запрос POST multipart/form-data, но без многочастного тела с файлом в нем

И если я помещаю его в options.data = {file: file};, он сериализуется независимо от того, установлено ли свойство processData true или нет.

4b9b3361

Ответ 1

Вы можете вручную генерировать MIME-данные для загрузки из данных файла HTML5, используя FileReader или аналогичные API. Проверьте: https://github.com/coolaj86/html5-formdata. Это будет делать более или менее, хотя это зависит от getAsBinary() - изменение его, чтобы также иметь возможность использовать FileReader и readAsBinaryString(), вероятно, было бы более совместимо с несколькими браузерами.

Обратите внимание, что это все еще не работает вообще в IE7/8, и, как говорили другие, нет способа сделать это, не прибегая к Flash или iframes. При этом, если вы используете File, предположительно, вы все равно не заботитесь о IE7 или IE8...

Ответ 2

Всякий раз, когда вы имеете дело с загрузкой произвольных данных с пользовательского компьютера, ответ обычно "нет, и если вы можете это сделать".

Это поражает меня как нечто, что подпадает под сферу нарушений безопасности. Вы не можете изменить значение элемента управления вводом файлов или сделать много других вещей, включая чтение истинного пути файла или его содержимого. Кроме того, на некоторых платформах у вас нет даже размера файла (IE, я смотрю на вас) без появления какого-либо диалога безопасности (через элемент управления activex). Учитывая все эти проблемы, я, вероятно, соблазню сказать, что даже если вы нашли решение, оно потенциально будет рассматриваться как ошибка в будущем и удалено или изменено.

Другими словами, я не думаю, что это безопасно, если вы не найдете авторитетного источника, явно поддерживающего его... например, блог Chrome Chrome.

Ответ 3

Я сам использовал valums ajax uploader. Вы можете получить его отсюда: http://valums.com/ajax-upload/. Он работает очень красиво. Я не знаю точную информацию о реализации, но здесь очень короткое описание:

"Этот плагин использует XHR для загрузки нескольких файлов с индикатором прогресса в FF3.6 +, Safari4 +, Chrome и возвращается к скрытой загрузке на основе iframe в других браузерах, обеспечивая хорошую работу пользователей во всем мире."

Итак, это похоже на то, что вы очень близки к тому, что вы хотите. Здесь еще немного информации о том, как она работает с точки зрения серверов (с сервера /readme.txt):

  • Для IE6-8, Opera, более старых версий других браузеров вы получаете файл как вы обычно делаете с обычной загрузкой на основе формы.

  • Для браузеров, которые загружают файл с индикатором выполнения, вам нужно получить опубликовать данные и записать их в файл.

Таким образом, это требует специальной обработки на стороне сервера. К счастью, он поставляется с несколькими реализациями на стороне справочного сервера (perl, php и java), так что это не должно быть слишком много хлопот. Happy ajax uploading:)

Ответ 4

Как я могу загружать файлы асинхронно?

Кажется, вы не можете сделать это, не пройдя iFrame. По-видимому, в ответе, который я связал, есть рабочие фрагменты и несколько плагинов, которые делают это за вас.

* изменить, так как я получаю комментарии к нему *

Да, возможно - http://caniuse.com/xhr2 - нет поддержки IE ниже 10, хотя..

Вот учебник:

http://www.html5rocks.com/en/tutorials/file/xhr2/

http://www.profilepicture.co.uk/ajax-file-upload-xmlhttprequest-level-2/