Загрузка файла 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
(простой простой текст с сервера).
Идеи?
Ответы
Ответ 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);