Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

uploading a file in chunks using html5

Tags:

I am trying to upload a file in chunks using html5's File API and then reassembling it on the server side in php. I am uploading a video but when i merge the files in server side the size has increased and it is becoming a invalid file . Please note the below html5 code only works in browser chrome . Tested in Chrome 9 as this uses file API's slice function . Can some one guide me on this ? Thanks

PHP source

<?php  $target_path = "uploads/"; $tmp_name = $_FILES['fileToUpload']['tmp_name']; $size = $_FILES['fileToUpload']['size']; $name = $_FILES['fileToUpload']['name'];   $target_file = $target_path . basename($name);   $complete = "complete.mov"; $com = fopen("uploads/".$complete, "ab"); error_log($target_path);  // Open temp file $out = fopen($target_file, "wb");  if ( $out ) {     // Read binary input stream and append it to temp file     $in = fopen($tmp_name, "rb");     if ( $in ) {         while ( $buff = fread( $in, 1048576 ) ) {             fwrite($out, $buff);             fwrite($com, $buff);         }        }     fclose($in);     fclose($out); } fclose($com);  ?> 

HTML Source

<!DOCTYPE html> <html>     <head>         <title>Upload Files using XMLHttpRequest</title>         <script type="text/javascript">              window.BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder;              function sendRequest() {                 var blob = document.getElementById('fileToUpload').files[0];                 const BYTES_PER_CHUNK = 1048576; // 1MB chunk sizes.                 const SIZE = blob.size;                 var start = 0;                 var end = BYTES_PER_CHUNK;                 while( start < SIZE ) {                     var chunk = blob.slice(start, end);                     uploadFile(chunk);                     start = end;                     end = start + BYTES_PER_CHUNK;                 }             }              function fileSelected() {                 var file = document.getElementById('fileToUpload').files[0];                 if (file) {                     var fileSize = 0;                     if (file.size > 1024 * 1024)                         fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB';                     else                         fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB';                      document.getElementById('fileName').innerHTML = 'Name: ' + file.name;                     document.getElementById('fileSize').innerHTML = 'Size: ' + fileSize;                     document.getElementById('fileType').innerHTML = 'Type: ' + file.type;                 }             }              function uploadFile(blobFile) {                 //var file = document.getElementById('fileToUpload').files[0];                   var fd = new FormData();                 fd.append("fileToUpload", blobFile);                  var xhr = new XMLHttpRequest();                 xhr.upload.addEventListener("progress", uploadProgress, false);                 xhr.addEventListener("load", uploadComplete, false);                 xhr.addEventListener("error", uploadFailed, false);                 xhr.addEventListener("abort", uploadCanceled, false);                 xhr.open("POST", "upload.php");                 xhr.onload = function(e) {                   alert("loaded!");                   };                  xhr.send(fd);                 //alert("oen over");             }              function uploadProgress(evt) {                 if (evt.lengthComputable) {                     var percentComplete = Math.round(evt.loaded * 100 / evt.total);                     document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';                 }                 else {                     document.getElementById('progressNumber').innerHTML = 'unable to compute';                 }             }              function uploadComplete(evt) {                 /* This event is raised when the server send back a response */                 alert(evt.target.responseText);             }              function uploadFailed(evt) {                 alert("There was an error attempting to upload the file.");             }              function uploadCanceled(evt) {                 xhr.abort();                 xhr = null;                 //alert("The upload has been canceled by the user or the browser dropped the connection.");             }         </script>     </head>     <body>         <form id="form1" enctype="multipart/form-data" method="post" action="upload.php">             <div class="row">                 <label for="fileToUpload">Select a File to Upload</label><br />                 <input type="file" name="fileToUpload" id="fileToUpload" onchange="fileSelected();"/>                 <input type="button" value="cancel"  onClick="uploadCanceled();"/>             </div>             <div id="fileName"></div>             <div id="fileSize"></div>             <div id="fileType"></div>             <div class="row">                 <input type="button" onclick="sendRequest();" value="Upload" />             </div>             <div id="progressNumber"></div>         </form>     </body> </html> 
like image 747
Vidya Avatar asked Oct 21 '11 18:10

Vidya


People also ask

How do I upload a file to chunks?

To perform a resumable file upload, user need to break the file into multiple chunks and upload these chunks to the image store one-by-one. Chunks don't have to be uploaded in order. If the file represented by the image store relative path already exists, it will be overwritten when the upload session commits.

How do I handle large uploads?

Possible solutions: 1) Configure maximum upload file size and memory limits for your server. 2) Upload large files in chunks. 3) Apply resumable file uploads. Chunking is the most commonly used method to avoid errors and increase speed.

How do you upload a file in HTML?

The <input type="file"> defines a file-select field and a "Browse" button for file uploads. To define a file-select field that allows multiple files to be selected, add the multiple attribute. Tip: Always add the <label> tag for best accessibility practices!

What is the best way to upload large files using JavaScript?

It’s worth noting that there are several existing JavaScript libraries like FineUploader and jQuery File Upload that can also upload large files, and in many cases, it makes more sense to use an existing library instead of reinventing the wheel.

How do I upload a large file in PHP?

If you’ve spent any amount of time messing with PHP config files to get a file to upload, you know that uploading large files can be a real pain. You have to find the loaded php.ini file, edit the upload_max_filesize and post_max_size settings, and hope that you never have to change servers and do all of this over again.

How to upload a file from HTML form using DBI?

The HTML form doesn’t do anything yet, so let’s create the dbi-file-uploader.js file and add an event handler for the upload button. After selecting the file object and creating the FileReader object, it will call upload_file () to start the read operation:

How to split a file into chunks using uuidv4?

const _fileID = uuidv4 () + "." + _file.name.split ('.').pop (); At this point we have the file to be uploaded, the number of chunks it will be split into, also beware we set fileID to ensure the name of the file will be unique in the remote source once it's done


1 Answers

I tried to solve this problem and found the following things, which hopefully will be of use to you:

1) The JS function you are using for slicing the file is deprecated. I am running Chrome v14 and the console didn't recognize it. I had to change it to this before I could do anything:

var chunk = blob.webkitSlice(start, end); 

2) I experimented with much smaller files (about 10MB), but had similar problems - my video was always corrupted after upload. When I compared the original and the 'copy' I noticed one thing peculiar: it seemed like the parts of the file were just mixed up - it was all there but in the wrong order.

I suspect one problem your current program suffers from is not taking measures to make sure that the files are assembled in the correct order. I believe what is happening is that your JS is running uploadFile several times, without waiting for the previous uploads to finish, and the server tries to assemble the files in the order it is received, but that is not the same order the files are sent.

I was able to prove this by getting your code to work (somewhat modified, hacked together just as a proof of concept), by assigning each file a sequence number as it was received, and then after all parts were received assembling them in order. After doing that, I was able to play my video file, after having uploaded it.

I think you are going to have to take a similar measure. Receive all the file chunks, and then assemble them, or at least make sure you're taking the necessary measures to assemble them in order. I'm not sure why your files would grow in size (I did observe this phenomenon, early on), so I suspect it is simply some bizarre side effect from otherwise not synchronizing the file chunks.

One difficulty you are immediately going to have is that the Blob object in Javasacript does not support changing or setting the file name, so you cannot on the client-side give the file a unique identifier that way. What I did, as a simple work around was the following:

            var i = 1;             while( start < SIZE ) {                 var chunk = blob.webkitSlice(start, end);                 uploadFile(chunk, i);                 i++;                  start = end;                 end = start + BYTES_PER_CHUNK;             }   function uploadFile(blobFile, part) {      ....      xhr.open("POST", "test.php?num=" + part);      .... } 

As you can probably guess on the server side, I just then, use that GET variable to assign an identifier, and use that as a the basis for any other processing that needs to be done on the server.

Anyways, this doesn't directly address the issue of the file size growing, so I can only hope this will help you; I'm curious to see what else you find out!

like image 188
user470714 Avatar answered Oct 21 '22 11:10

user470714