I'm using file api and xhr2 spec. I created an uploader (backed by flash for older browsers) that was using FormData
and $.ajax(options)
where the FormData object with File
was part of options.data
object. Everything was working.
Now I decided to remove FormData
because of weak browser support. And I can't figure a way to upload the file other than
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);
Which doesn't return Promise that I can use in the recursion function.
My code is like this :
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();
}
},
To make it short, $.ajax(options)
resolves into xhr.send(formData)
if options.data = FormData
but how do I make it resolve into xhr.send(file)
?
EDITED: I was playing with it and if I set options.data = file; then $.ajax(options) executes xhr.send(theFile); but with error Error: INVALID_STATE_ERR: DOM Exception 11
and the request is sent as POST multipart/form-data request, but without the multipart body with file in it
And if I put it into options.data = {file: file};
it is serialized no matter if processData
property is set to true or not.
You can manually generate the MIME data for the upload from the HTML5 file data read using FileReader
or similar APIs. Check out: https://github.com/coolaj86/html5-formdata . This will do more or less that, although it depends on getAsBinary()
-- changing it to also be able to use FileReader
and readAsBinaryString()
would probably be more cross-browser-compatible.
Note that this still won't work at all in IE7/8, and as others have said, there is no way to do it without resorting to Flash or iframes. That being said, if you're using File, presumably you don't care about IE7 or IE8 anyway...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With