I need to upload a part of a file (only the first MB). I've created a PHP script which uploads the whole file. The data (formData
Object) is passed by a ajax call.
My idea would be now to split the file with javascript (jquery). Is there any solution for my request?
Current code:
function start(a){
//var fSize = $('#fileUpload')[0].files[0].size / 1024;
var formData = new FormData();
formData.append( 'fileUpload', $('#fileUpload')[0].files[0] );
//AJAX
$.ajax({
url: 'script.php',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(msg){
alert("Win: " + msg);
},
error: function(bla, msg){
alert("Fail: " + msg);
}
});
}
I need to upload a part of a file (only the first MB). I've created a PHP script which uploads the whole file. The data (formData
Object) is passed by a ajax call.
My idea would be now to split the file with javascript (jquery). Is there any solution for my request?
Current code:
function start(a){
//var fSize = $('#fileUpload')[0].files[0].size / 1024;
var formData = new FormData();
formData.append( 'fileUpload', $('#fileUpload')[0].files[0] );
//AJAX
$.ajax({
url: 'script.php',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(msg){
alert("Win: " + msg);
},
error: function(bla, msg){
alert("Fail: " + msg);
}
});
}
Share
Improve this question
edited Aug 21, 2012 at 13:04
bfavaretto
71.9k18 gold badges117 silver badges159 bronze badges
asked Aug 21, 2012 at 12:59
SylnoisSylnois
1,6316 gold badges26 silver badges51 bronze badges
5
- 3 You don't have any access to the content file in JavaScript. There is no way to split it. And BTW there is no way to post a file with AJAX either. – RoToRa Commented Aug 21, 2012 at 13:02
- @RoToRa Why don't you post it as an answer? – user657496 Commented Aug 21, 2012 at 13:14
- 2 @RoToRa Well, actually there's a way - with new FileReader API. But somehow I think it's not relevant here. ) – raina77ow Commented Aug 21, 2012 at 13:14
- @user1515190 I suppose this article might be helpful for you. But take note that tools used in it are not universally supported... yet. – raina77ow Commented Aug 21, 2012 at 13:21
- @RoToRa ehm, this script above works. – Sylnois Commented Aug 21, 2012 at 13:46
1 Answer
Reset to default 21Since you're using FormData
, which is a fairly new technology, I'll show you something with new technologies as well.
First, read the file with a FileReader
object:
var fr = new FileReader(), buf, file = $('#fileUpload')[0].files[0];
fr.onload = function(e) {
buf = new Uint8Array(e.target.result);
};
fr.readAsArrayBuffer(file);
Then you can create a Blob
for each splitted part (1e6
bytes long each):
for (var i = 0, blobs = []; i < buf.length; i += 1e6)
blobs.push(new Blob([buf.subarray(i, i + 1e6)]));
Finally, you can add all your Blob
s to your FormData
object:
var formData = new FormData();
for (var i = 0; i < blobs.length; i++)
formData.append("slice" + i, blobs[i], file.name + ".part" + i);
You should be ok. I haven't tested it, though.
I don't know anything about the performance either. You can use fr.readAsBinaryString
too, thus making e.target.result
a string. This way, you can create the Blob
s using a simple substring
/slice
/substr
/whatever, but I fear there could be some problems with Unicode characters and whatnot. Plus, maybe it's slower.
Putting everything in a more coherent snippet:
$('#fileUpload').change(function() {
// If no file is selected, there's nothing to do
if (!this.files.length) return;
var fr = new FileReader(), file = this.files[0];
fr.onload = function(e) {
splitAndSendFile(new Uint8Array(e.target.result), file);
};
fr.readAsArrayBuffer(file);
};
function splitAndSendFile(dataArray, file) {
var i = 0, formData, blob;
for (; i < dataArray.length; i += 1e6) {
blob = new Blob([dataArray.subarray(i, i + 1e6)]);
formData = new FormData();
formData.append("fileUpload", blob, file.name + ".part" + (i / 1e6));
$.ajax({
url: 'script.php',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(msg){
alert("Win: " + msg);
},
error: function(bla, msg){
alert("Fail: " + msg);
}
});
}
}
Note: FormData.append
takes a third optional parameter, which should be the name of the file in case of File
or Blob
values. If not specified, Blob
s may get unpredictable random file names.
Probably that parameter isn't standard, and it's not mentioned in the MDN artice, but I used it in the snippet above nonetheless. Anyway, if you know what you're doing, you can have several options to specify the file name. For example, with formData.append("filename", file.name)
or sending a custom header in the request.