Можно ли загрузить файл только через $ .ajax (параметры) или xhr.send (файл)? - PullRequest
12 голосов
/ 24 мая 2011

Я использую файл 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);

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

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

   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)?

ИЗД.это и если я установлю 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 или нет.

Ответы [ 4 ]

2 голосов
/ 05 июня 2011

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

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

0 голосов
/ 31 мая 2011

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

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

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

0 голосов
/ 02 июня 2011

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

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

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

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

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

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

0 голосов
/ 24 мая 2011

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

Кажется, вы не можете сделать это без прохождения через 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/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...