HTML5 snippet, the result file is corrupted

I have the function of downloading files and using slice api from html5, I cut each file into 1 MB piece, but the final result leads to file corruption. sometimes the end result is smaller than the original file, and sometimes even with the right size, I still can't open it. who has an idea? or solution? This is part for slicing

var uploaders = []; var i = 0; $(document).ready(function() { var progress = document.querySelector('progress'); var bars = document.querySelector('#bars'); }); //function for after the button is clicked, slice the file //and call upload function function sendRequest() { //clean the screen bars.innerHTML = ''; var blob = document.getElementById('fileToUpload').files[0]; var originalFileName = blob.name; const BYTES_PER_CHUNK = 1 * 1024 * 1024; // 10MB chunk sizes. const SIZE = blob.size; var start = 0; var end = BYTES_PER_CHUNK; while( start < SIZE ) { if (blob.webkitSlice) { var chunk = blob.webkitSlice(start, end); } else if (blob.mozSlice) { var chunk = blob.mozSlice(start, end); } uploadFile(chunk, originalFileName); start = end; end = start + BYTES_PER_CHUNK; } } function uploadFile(blobFile, fileName) { var progress = document.createElement('progress'); progress.min = 0; progress.max = 100; progress.value = 0; bars.appendChild(progress); var fd = new FormData(); fd.append("fileToUpload", blobFile); var xhr = new XMLHttpRequest(); xhr.open("POST", "upload.php"+"?"+"file="+fileName + i, true); i++; xhr.onload = function(e) { //make sure if finish progress bar at 100% progress.value = 100; //counter if everything is done using stack uploaders.pop(); if (!uploaders.length) { bars.appendChild(document.createElement('br')); bars.appendChild(document.createTextNode('DONE :)')); } }; // Listen to the upload progress for each upload. xhr.upload.onprogress = function(e) {; if (e.lengthComputable) { progress.value = (e.loaded / e.total) * 100; } }; uploaders.push(xhr); xhr.send(fd); } 

and this is a php file for receiving a binary fragment

 <?php $target_path = "uploads/"; $tmp_name = $_FILES['fileToUpload']['tmp_name']; $size = $_FILES['fileToUpload']['size']; $name = $_FILES['fileToUpload']['name']; $originalName = $_GET['file1']; print_r("*******************************************\n"); print_r($originalName); print_r("\n"); print_r($_FILES); print_r("\n"); print_r("*******************************************\n"); $target_file = $target_path . basename($name); //Result File $complete = $originalName; $com = fopen("uploads/".$complete, "ab"); error_log($target_path); if ( $com ) { // Read binary input stream and append it to temp file $in = fopen($tmp_name, "rb"); if ( $in ) { while ( $buff = fread( $in, 1048576 ) ) { fwrite($com, $buff); } } fclose($in); fclose($com); } ?> 

I think I did something wrong when I put the file on the server with my php code (for example, I did not put it in order or something else), but does anyone know how to do this or can to be better? Instead of loading the file and then merging it, you may first store it in memory before writing it to the file.

+4
source share
1 answer

Download several pieces of the file at once, then merge them to the end.

 const BYTES_PER_CHUNK = 1024 * 1024; // 1MB chunk sizes. var slices; var slices2; function sendRequest() { var xhr; var blob = document.getElementById('fileToUpload').files[0]; var start = 0; var end; var index = 0; // calculate the number of slices we will need slices = Math.ceil(blob.size / BYTES_PER_CHUNK); slices2 = slices; while(start < blob.size) { end = start + BYTES_PER_CHUNK; if(end > blob.size) { end = blob.size; } uploadFile(blob, index, start, end); start = end; index++; } } function uploadFile(blob, index, start, end) { var xhr; var end; var fd; var chunk; var url; xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if(xhr.readyState == 4) { if(xhr.responseText) { alert(xhr.responseText); } slices--; // if we have finished all slices if(slices == 0) { mergeFile(blob); } } }; if (blob.webkitSlice) { chunk = blob.webkitSlice(start, end); } else if (blob.mozSlice) { chunk = blob.mozSlice(start, end); } fd = new FormData(); fd.append("file", chunk); fd.append("name", blob.name); fd.append("index", index); xhr.open("POST", "upload.php", true); xhr.send(fd); } function mergeFile(blob) { var xhr; var fd; xhr = new XMLHttpRequest(); fd = new FormData(); fd.append("name", blob.name); fd.append("index", slices2); xhr.open("POST", "merge.php", true); xhr.send(fd); } 

Collect fragments using upload.php:

 if(!isset($_REQUEST['name'])) throw new Exception('Name required'); if(!preg_match('/^[-a-z0-9_][-a-z0-9_.]*$/i', $_REQUEST['name'])) throw new Exception('Name error'); if(!isset($_REQUEST['index'])) throw new Exception('Index required'); if(!preg_match('/^[0-9]+$/', $_REQUEST['index'])) throw new Exception('Index error'); if(!isset($_FILES['file'])) throw new Exception('Upload required'); if($_FILES['file']['error'] != 0) throw new Exception('Upload error'); $target = "uploads/" . $_REQUEST['name'] . '-' . $_REQUEST['index']; move_uploaded_file($_FILES['file']['tmp_name'], $target); // Might execute too quickly. sleep(1); 

Merge the parts using merge.php:

 if(!isset($_REQUEST['name'])) throw new Exception('Name required'); if(!preg_match('/^[-a-z0-9_][-a-z0-9_.]*$/i', $_REQUEST['name'])) throw new Exception('Name error'); if(!isset($_REQUEST['index'])) throw new Exception('Index required'); if(!preg_match('/^[0-9]+$/', $_REQUEST['index'])) throw new Exception('Index error'); $target = "uploads/" . $_REQUEST['name']; $dst = fopen($target, 'wb'); for($i = 0; $i < $_REQUEST['index']; $i++) { $slice = $target . '-' . $i; $src = fopen($slice, 'rb'); stream_copy_to_stream($src, $dst); fclose($src); unlink($slice); } fclose($dst); 
+8
source

Source: https://habr.com/ru/post/1401230/


All Articles