загрузка файла jquery - IE выполнил обратный вызов data.result - PullRequest
30 голосов
/ 11 января 2012

Я использую jQuery файл плагин загрузки .

Я не использую UI часть, только базовую.

Когда я делаюследующее, у меня проблема в IE:

$('input#fileupload').fileupload({
    url: '/upload',
    done: function (e, data) {
    if(data.result != null && $.trim(data.result) != '')
        $('a#attachment').html(data.result);
    }
    //......................

на IE data.result это Object (IE9 по крайней мере, не уверен, что другие ...)

Вкл. Chrome / Firefox - это просто ответ Text (простой текст с сервера).

Идеи?

Ответы [ 8 ]

50 голосов
/ 17 января 2012

Я только что столкнулся с той же проблемой, и я думаю, что это связано с тем, что загрузка файлов XHR не поддерживается в IE (даже 9).Вот то, что, как я полагаю, происходит, и мое решение:

Поскольку Safari 5+, Firefox 4+ и Chrome поддерживают загрузку файлов XHR, плагин fileupload может передавать файлы действительно асинхронно, что позволяет получить чистый текстовый ответ отсервер.Этот чистый текстовый ответ доступен через data.result в обработчике done и может быть легко использован.

Однако в IE передача файла происходит через полное обновление страницы в скрытом фрейме, что приводит кdata.result в обработчике done является полным document объектом с текстом ответа, завернутым глубоко в теги <html><body><iframe><pre>.

Мало того, что это затрудняет доступ к данным вТо есть, это делает способ доступа к данным разным в разных браузерах.

Мое решение:

Я установил для параметра forceIframeTransport значение true, что позволяет всем браузерам передавать файлы со скрытым iframe., как IE.К сожалению, упустить загрузку файлов XHR, но это, по крайней мере, дает нам одинаковый ответ во всех браузерах.Затем в моем обработчике done я извлек результат из объекта document следующим образом:

var result = $( 'pre', data.result ).text();

В вашем случае, я думаю, код будет выглядеть примерно так:

$('input#fileupload').fileupload({
    forceIframeTransport: true,
    url: '/upload',
    done: function ( e, data ) {
     var result = $( 'pre', data.result ).text();
     if( result != null && $.trim( result ) != '' )
        $( 'a#attachment' ).html( result );
    }
...

Также важно отметить, что тип содержимого ответа от моего сервера - «text / plain».Как вы могли заметить, IE иногда предлагает пользователю сохранить или открыть ответ json.

Вот несколько ссылок, которые оказались полезными при решении проблемы: https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support (см. Раздел «XMLHttpRequest»).внизу) https://github.com/blueimp/jQuery-File-Upload/wiki/Options (см. «forceIframeTransport» примерно на 1/3 пути вниз)

Надеюсь, это поможет!

13 голосов
/ 29 августа 2012

У меня были проблемы, подобные упомянутым выше, и я обнаружил, что изменение типа ответа с application/json на text/plain устранило эти проблемы.

5 голосов
/ 23 октября 2013

На самом деле это то, для чего jquery.iframe-transport.js (базовая версия также включает этот плагин в качестве дополнительной ссылки).Вам нужно установить для свойства dataType значение json, а плагин jquery.iframe-transport автоматически проанализирует результат iframe, чтобы вы могли использовать ту же логику в обработчике done.

$('#fileupload').fileupload({
...
    dataType: 'json'
...
});
4 голосов
/ 19 апреля 2012

Я столкнулся с этой же проблемой. IE 9 не будет вызывать обратный вызов done, но будет вызывать обратный вызов always. Сложно было извлечь объект ответа JSON из аргументов. (Несмотря на то, что заявлено в документации, я не нашел, что мне нужно было включать jquery.iframe-transport.js.)

Моя реализация обратного вызова always выглядела примерно так:

always: function(e, data) {
  var result;
  if (data.textStatus == 'parsererror') {  // IE9 fails on upload's JSON response
    result = JSON.parse(data.jqXHR.responseText);
  } else if (data.textStatus == 'success') {
    result = data.result;
  }

  if (result) {
    // ...perform custom handling...
  }
}
1 голос
/ 22 ноября 2013

Ответы здесь были очень полезны для понимания и решения проблемы. Я получил удовлетворительное, хотя и хакерское решение, которое позволяет современным браузерам загружать с использованием XmlHttpRequest, а IE9 использовать iframe (не тестировал с IE7 / 8):

  • Используйте jquery.iframe-transport.js, он позаботится о извлечении ответа из iframe. Просто включите его на странице, плагин fileupload будет использовать его.
  • На серверном действии, используемом для загрузки файлов, верните результат JSON, но с content-type, установленным на "text/plain", чтобы IE не предлагал пользователю открыть файл
  • В обработанном обратном вызове вручную вычислите текст JSON
  • Наконец, используйте оцененный объект результата, как и раньше

Вот код JS:

//file upload
var upload = $(fileUploadElmtId).fileupload({

    dataType: 'text',  //if we use JSON IE9 will ask the user to open the file... see the FileUploadController class
    url: uploadUrl,
    autoUpload: true,

    done: function (e, data) {


        //parse the JSON string that was received from the server - since it was received as text/plain it is not automatically evaluated
        var result = $.parseJSON(data.result);

        $.each(result.files, function (index, file) {
            //do something with the result - in my case it is an array of uploaded files...
        }
    }
}
0 голосов
/ 23 января 2017

Моя проблема, причина: междоменный.

То есть: в IE8 / 9 URL вашего сервера должен находиться в том же домене, что и ваш файл js. Для jquery.iframe-transport.js основан на iframe, в котором вы не можете междоменный. Проверьте хех

Вам не нужно устанавливать для ForceIframeTransport значение true, поскольку jquery.file-upload.js будет оценивать сам браузер.

Ваш сервер должен вернуть Content-Type: text / html или, возможно, text / plain, и ваши js могут использовать dataType: 'json', нет проблем. По крайней мере, мой.

Когда вы отлаживаете, вы можете установить точку останова в jquery.iframe-transport.js примерно на line85, блок try / catch. Если это может сломаться, это означает, что используется iframe, и вы можете получить ответ. В это время вы могли видеть свой JSON в DOM (в iframe), но если бы вы пересекались, вы бы получили ответ как неопределенный.

Мой код. Никаких специальных:

$('.input-upload').fileupload({
    url: url, 
    dataType: 'json',
    autoUpload: false,
    acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
    maxFileSize: 999000,
    previewMaxWidth: 114,
    previewMaxHeight: 70,
    previewThumbnail: false,
    xhrFields: {
        withCredentials: true
    }
}).on('fileuploadadd', function (e, data) {
    $.each(data.files, function (index, file) {
        data.submit().success(function (json, textStatus, jqXHR) {
            // on success
        }).error(function (jqXHR, textStatus, errorThrown) {
            // on error
        });
    });
}).on('fileuploadprocessalways', function (e, data) {
    var _this = this;
    var file = data.files[data.index];
    if (file.preview) {
        // 显示图片预览
        var preview = $(this).parent().siblings('.preview');
        preview.append(file.preview).removeHide();
    }
});
0 голосов
/ 02 июля 2013

Спасибо @Justin за отличное объяснение этого.Я бы не стал делать запросы для элемента «pre», а вместо этого делал бы простое решение, например, закомментированное @ EnsignRicky

done: function (e, data) {
  var result = data.result[0].body ? data.result[0].body.innerHTML : data.result
}
0 голосов
/ 11 января 2012

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

header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . "GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
header("Content-type: text/x-json");
echo json_encode($array);
exit(0);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...