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);
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);
source share