Split file with JavaScript or jQuery
Since 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.
Sylnois
Updated on June 03, 2022Comments
-
Sylnois almost 2 years
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); } }); }
-
RoToRa over 11 yearsYou 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.
-
Admin over 11 years@RoToRa Why don't you post it as an answer?
-
raina77ow over 11 years@RoToRa Well, actually there's a way - with new FileReader API. But somehow I think it's not relevant here. )
-
raina77ow over 11 years@user1515190 I suppose this article might be helpful for you. But take note that tools used in it are not universally supported... yet.
-
Sylnois over 11 years@RoToRa ehm, this script above works.
-
-
Sylnois over 11 yearsThanks for your reply. I don't want to send the whole array, just part for part(so i can control the progressbar), but somehow it does not work(link to my script at the end). My PHP-Script is a simple command(move_uploaded_file($_FILES["fileUpload"]["tmp_name"], $uploadPath . $_FILES["fileUpload"]["name"]);). I want to fit the parts together serverside. 193.109.52.60/dario/f
-
MaxArt over 11 years@user1515190 It doesn't work because of a syntax error in the
blob.push(...
line. Missed a closing parenthesis, my bad. You can try it again. -
Sylnois over 11 yearsstill not working :/ PS: Really thanks for your help! I try this for weeks(not full-time of course :D)
-
MaxArt over 11 years@user1515190 Ah, I get it. Now the problem is in your code. I didn't put everything in a complete form, but it can't be done in a synchronous way. I'll give you a hint about it, in the answer.
-
Sylnois over 11 yearsSomething still not right. I've tried to debug my code with alerts. Alert 6 does not appaer(after this code section: blob = new Blob([dataArray.subarray(i, i + 1e6)]);
-
MaxArt over 11 years@user1515190 It works perfectly for me, "bla6" is alerted and then I get a "Win" alert with the size of the sent chunk. I'm using Chrome 22 dev. Why don't you debug with the developer tools of your browser instead of the old fashioned alerts? Which one are you using?
-
Sylnois over 11 yearsi can see your files(AEVLX.gif.part0 - part2). I'm using Chrome 18.0.1025.162. When i try to upload a ZIP-file, nothing happens. Only the first four alerts appear.
-
Sylnois over 11 yearsi updated my google chrome to 21 and now it works.. but whats with the people with older browser?
-
Sylnois over 11 yearslarge files still not working :( browser crashes after trying to upload a 25 MB big RAR-file
-
MaxArt over 11 years@user1515190 That's probably because of a memory overflow of some sort. I don't think file splitting is a task for browsers, anyway: that's the major problem. People with older browsers... well, should upgrade before using your app. Chrome, Firefox and Opera usually upgrades automatically. IE is out of question in this case, so you shouldn't worry about it. It's not a tragedy to ask your users to upgrade to browsers with a good HTML5 support.
-
Sylnois over 11 yearsIt is, cause in many companies is the ie(an older version) default and the employees can't just upgrade the software, but many THANKS four your help, really! A last question: i've done this partions that i can show up an progressbar. Do you know another way to show up an progressbar with JQuery? without flash or any other extensions :)
-
MaxArt over 11 years@user1515190 IE, even IE9, doesn't support
FormData
, nor XHR2 requests, so you're out of luck with this bunch of code. If your aim was to show a progress bar, then you could just rely on theonprogress
event of theupload
member of the XHR object, getting a much better result than all the pain we got through. As for the progress bar, I'd suggest to use some common jQuery plugins, for example the progress bar of jQuery UI, which is like an "official" widget library for jQuery. (BTW, can you accept my answer if it helped you?) -
Thomas over 8 yearswhat is FormData and FileReader class?
-
MaxArt over 8 years@Thomas They're API that are part of the XHR2 standard interface. They're available in IE10+ and evergreen browsers.
-
Karan Bhandari over 6 yearsThank you, used your code as base to do the same with angular js. github.com/kurtzace/angular-multipart-smaller-chunks