Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript large file uploader

I copied a code online to upload a large file to my server. It basically cut the large file into chunks and send then end them individually. So the first chunk get successfully sent to the server, but the rest just does not work. I am not sure which stage cause the problem, can someone please help.

<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 i =0;
                var part = 0;
                while( start < SIZE ) {
                    var chunk = blob.slice(start, BYTES_PER_CHUNK);
                    //alert(chunk.size());
                    uploadFile(chunk,part);
                    //alert("here");
                    start = start + BYTES_PER_CHUNK;
                    part++;
                }
            }

            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,part) {
                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"+"?"+"file="+file.name+"&num=" + part);
                xhr.onload = function(e) {
                  //alert("loaded!");
                  };

                xhr.setRequestHeader('Cache-Control','no-cache');
                xhr.send(fd);
                return;
                //while(xhr.readyState!=4){}
                //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>

the Code on the Server

$target_path = "uploads/";
$tmp_name = $_FILES['fileToUpload']['tmp_name'];
$size = $_FILES['fileToUpload']['size'];
$name = $_FILES['fileToUpload']['name'];
$sports = $_GET['file'];
$part =(string)$_GET['num'];
//$part = split("/\=/", $part);
$target_file = $target_path .$part. $sports;


// 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);
        }   
    }
    fclose($in);
    fclose($out);
}

  ?>
like image 711
user1890228 Avatar asked Dec 09 '12 22:12

user1890228


People also ask

How to upload large file using JavaScript?

To enable the chunk upload, set the size to chunkSize option of the upload and it receives the value in bytes . The chunk upload functionality separates the selected files into blobs of the data or chunks. These chunks are transmitted to the server using an AJAX request.

How can I send large files via HTTP?

We have three ways to shorten the time sending extensive data by HTTP: compress data. send chunked data. request data in a selected range.

Can we upload file using JavaScript?

html file through a browser, the client will be able to upload a file to the server using Ajax and pure JavaScript. A pure JavaScript file uploader simplifies Ajax based interactions with the server.

What is Plupload?

Plupload is a JavaScript API for dealing with file uploads it supports features like multiple file selection, file type filtering, request chunking, client side image scaling and it uses different runtimes to achieve this such as HTML 5, Silverlight and Flash.


3 Answers

There is a glitch in the code above. You are calling uploadFile in while loop like this..

            while( start < SIZE ) {
                var chunk = blob.slice(start, BYTES_PER_CHUNK);
                //alert(chunk.size());
                uploadFile(chunk,part);
                //alert("here");
                start = start + BYTES_PER_CHUNK;
                part++;
            }

You are not waiting for chunk to load successfully !! You keep on uploading the chunks until the end. You can wait for one chunk to upload successfully and then load the next.

I feel you can try the following ..

     var blob;
     var start;
     var part;
     var chunk;
     const SIZE = blob.size;
     var xhr;
     function sendRequest() {
            blob = document.getElementById('fileToUpload').files[0];
            const BYTES_PER_CHUNK = 1048576; // 1MB chunk sizes.
            const SIZE = blob.size;
            start = 0;                
            part = 0;
            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"+"?"+"file="+file.name+"&num=" + part);
            xhr.onload = function(e) {
              //alert("loaded!");
              };

            xhr.setRequestHeader('Cache-Control','no-cache');
            chunk = blob.slice(start, BYTES_PER_CHUNK);
            //alert(chunk.size());
            uploadFile(chunk,part);
            //alert("here");
            start = start + BYTES_PER_CHUNK;
            part++;                
        }
function uploadFile(blobFile,part) {
            var file = document.getElementById('fileToUpload').files[0];  
            var fd = new FormData();
            fd.append("fileToUpload", blobFile);


            xhr.send(fd);
            return;
            //while(xhr.readyState!=4){}
            //alert("oen over");
        }

function uploadComplete(evt) {
            /* This event is raised when the server send back a response */
            alert(evt.target.responseText);
            while( start < SIZE ) {
                chunk = blob.slice(start, BYTES_PER_CHUNK);
                //alert(chunk.size());
                uploadFile(chunk,part);
                //alert("here");
                start = start + BYTES_PER_CHUNK;
                part++;
            }
        }
like image 116
Yugandhar Pathi Avatar answered Oct 19 '22 23:10

Yugandhar Pathi


The reason that the rest are not uploading is that your slice loop is not right. change it to the following and you should be golden.

var start = 0;
var end = BYTES_PER_CHUNK;
var part = 0;
while( start < SIZE ) {
    var chunk = blob.slice(start, end);
    uploadFile(chunk,part);
    start = end;
    end = start + BYTES_PER_CHUNK;
    part++;
}
like image 30
Steve Lloyd Avatar answered Oct 20 '22 01:10

Steve Lloyd


The .JS script here, uploads the blob in chunks successfully.

window.BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder;
        var blob; var blob_1;
        var start; var end;
        var num; var part;
        var SIZE; var size; var fileSize = 0;
        var BYTES_PER_CHUNK; var NUM_CHUNKS; var chunk; var chunk_size = 0;
        var xhr; var counter = 0;
        
        function sendRequest() {

            blob = document.getElementById('file').files[0];
            // blob = new Blob(blob_1, {type: 'video/mp4'}); 
                const BYTES_PER_CHUNK = 1048576; // 1MB chunk sizes.
                const SIZE = blob.size;
                var i = 0;
                var start = 0;
                var end = BYTES_PER_CHUNK;
                var part = 0;
                var NUM_CHUNKS = Math.max(Math.ceil(SIZE / BYTES_PER_CHUNK), 1);
                
                while( start < SIZE ) {
                    var chunk = blob.slice(start, end);
                    uploadFile(chunk,part);
                    start = end;
                    end = start + BYTES_PER_CHUNK;
                    part++; counter++;
                }
        };

        function fileSelected() {
            var file = document.getElementById('file').files[0];
            if (file) {
                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,part) {
            
            var file = document.getElementById('file').files[0];  
            var fd = new FormData();
            fd.append("file", blobFile);  fd.append("chunk_num", NUM_CHUNKS);  
            var xhr = new XMLHttpRequest();
            xhr.upload.addEventListener("progress", uploadProgress, false);
            
            xhr.open("POST", "uploadhandler.php"+"?"+"filen="+file.name+"&num="+part+"&counter="+counter);
            
            
            xhr.addEventListener("load", uploadComplete, false);
            xhr.addEventListener("error", uploadFailed, false);
            xhr.addEventListener("abort", uploadCanceled, false);

            
            xhr.onload = function(e) {
              //alert("loaded!");
              };

            xhr.setRequestHeader('Cache-Control','no-cache');
            xhr.send(fd);
            return;
        }
        
        function uploadProgress(evt) {
            if (evt.lengthComputable) {
                var percentComplete = Math.round(evt.loaded * 100 / evt.total);
                document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';
                document.getElementById('progressBar').style.backgroundColor="teal";                
            }else {
                document.getElementById('progressNumber').innerHTML = 'unable to compute';
            }
        }

    function uploadComplete(evt) {
            
            if( start < SIZE ) {
                chunk = blob.slice(start, end);

                uploadFile(chunk,part);

                start = end;
                end = start + BYTES_PER_CHUNK;
                part = part + 1;
                
            }
            document.getElementById("msgStatus").innerHTML = evt.target.responseText;
            //alert("complete");
            
        }

        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.");
        } 

The .PHP code here stores each chunk in the "uploads/" folder

session_start();

    $counter = 1;
    $_SESSION['counter'] = ($_REQUEST['num'] + 1);
  
  // changing the upload limits
   ini_set('upload_max_filesize', '100M');
   ini_set('post_max_size', '100M');
   ini_set('max_input_time', 300);
   ini_set('max_execution_time', 300);

    $filePath = "uploads/";
    if (!file_exists($filePath)) {
        if (!mkdir($filePath, 0777, true)) {
            echo "Failed to create $filePath";
        }
    }
    
    // $newfile = $newfile ."_". $_SESSION['counter'] .".mp4";
    $target_path = 'uploads/';
    $tmp_name = $_FILES['file']['tmp_name'];
    $filename = $_FILES['file']['name'];
    $newfile = substr(md5($_FILES['file']['name']), 0,10);
    $target_file = $target_path.$newfile;
    move_uploaded_file($tmp_name, $target_file.$_SESSION['counter'] );

B.U.T. the following .PHP code does not merge the chunks.

I do not really understand why it is not fopening for reading and writing... If you have any ways of merging the chunks into one whole video file, please post your response likewise here.

// count number of uploaded chunks
    $chunksUploaded = 0;
    for ( $i = 1; $i <= $_SESSION['counter']; $i++ ) {
        if ( file_exists( $target_file.$i ) ) {
             $chunksUploaded++;
        }
    }

    // if ($chunksUploaded === $num_chunks) {
    if ($chunksUploaded === $_SESSION['counter']) {

        // here you can reassemble chunks together 
        // for ($i = 1; $i <= $num_chunks; $i++) {
        for ($i = 1; $i <= $_SESSION['counter']; $i++) {
            // echo $i ."\n";
          $file = fopen($target_file.$i, 'rb');
          $buff = fread($file, 1048576);
          fclose($file);

          $final = fopen($target_file, 'ab');
          $write = fwrite($final, $buff);
          fclose($final);

          unlink($target_file.$i);
        }
        
    }

Hope you enjoy and thank you for your contribution too.

like image 36
Easytime Games Avatar answered Oct 19 '22 23:10

Easytime Games