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

Загрузка файла jquery - IE сделал обратный вызов data.result issue

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

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

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

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

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

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

Идеи?

4b9b3361

Ответ 1

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

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

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

Это не только облегчает доступ к данным в IE, но и делает возможным доступ к данным, различным между браузерами.

Мое решение:

Я установил для параметра 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 пути вниз)

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

Ответ 2

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

Ответ 3

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

$('#fileupload').fileupload({
...
    dataType: 'json'
...
});

Ответ 4

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

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

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

  if (result) {
    // ...perform custom handling...
  }
}

Ответ 5

Ответы здесь были очень полезны для понимания и решения проблемы. Я закончил с удовлетворительным, если взломанным решением, которое позволяет загружать современные браузеры с помощью 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...
        }
    }
}

Ответ 6

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

done: function (e, data) {
  var result = data.result[0].body ? data.result[0].body.innerHTML : data.result
}

Ответ 7

Моя проблема, причина кросс-домена.

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

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

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

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

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

$('.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();
    }
});

Ответ 8

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

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