jquery file upload - IE done callback data.result issue
I'm using jQuery
file upload plugin.
I don't use the UI
part, only basic one.
When I do the following, I'm having an issue in IE
:
$('input#fileupload').fileupload({
url: '/upload',
done: function (e, data) {
if(data.result != null && $.trim(data.result) != '')
$('a#attachment').html(data.result);
}
//......................
on IE
the data.result
is an Object
(IE9
at least, not sure the others...)
On Chrome
/Firefox
is just the response Text
(simple plain text from the server).
Ideas?
I just ran into the same problem, and I think it is due to the fact that XHR file uploads are not supported in IE (even 9). Here's what I believe is happening, and my solution:
Since Safari 5+, Firefox 4+, and Chrome support XHR file uploads, the fileupload plugin can transfer the files truly asynchronously, allowing for a pure text response from the server. This pure text response is available via data.result
in the done
event handler, and can be used easily.
In IE, however, the file transfer occurs via a full page refresh in a hidden iframe, causing data.result
in the done
handler to be a full document
object, with the response text wrapped deep inside <html><body><iframe><pre>
tags.
Not only does this make it a pain to get to the data in IE, it makes the way you get to the data different between browsers.
My solution:
I set the forceIframeTransport
option to true, which makes all browsers transfer files with a hidden iframe, like IE. It's unfortunate to miss out on XHR file uploads, but this at least gives us the same kind of response in all browsers. Then, in my done
handler, I extracted the result from the document
object like so:
var result = $( 'pre', data.result ).text();
In your case, I think the code would look something like this:
$('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 );
}
...
Also important to note here is that the Content Type of the response from my server is 'text/plain'. As you may have noticed, IE sometimes prompts the user to save or open a json response.
Here are a couple links that proved useful when resolving the problem: https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support (see 'XMLHttpRequest' section at bottom) https://github.com/blueimp/jQuery-File-Upload/wiki/Options (see 'forceIframeTransport' about 1/3 of the way down)
Hopefully this helps!
I had problems similar to the ones mentioned above and found that changing the response type from application/json
to text/plain
fixed those issues.
Actually this is what the jquery.iframe-transport.js
is for (the basic version also include this plugin as additional reference). What you need is to set the dataType
property to json
and the jquery.iframe-transport
plugin will automatically parse the iframe
result, so you can have the same logic in your done handler.
$('#fileupload').fileupload({
...
dataType: 'json'
...
});
I ran into this same issue. IE 9 would not trigger the done
callback, but would trigger the always
callback. The tricky part was extracting the JSON response object from the arguments. (Despite what the documentation claimed, I did not find that I needed to include jquery.iframe-transport.js.)
My implementation of the always
callback looked something like this:
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...
}
}
The answers here were very useful to understand and solve the problem. I ended up with a satisfactory if hacky solution, that allows modern browsers to upload using XmlHttpRequest
, and IE9 to use iframe
(didn't test with IE7/8) :
- Use
jquery.iframe-transport.js
, it will take care of extracting the response from the iframe. Just include it in the page, thefileupload
plugin will use it. - On the server action used to upload the files, return a JSON result, but with
content-type
set to"text/plain"
, in order to avoid IE prompting the user to open the file - In the done callback, manually evalutate the JSON text
- Finally, use the evaluated result object as before
Here is the JS code :
//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...
}
}
}