Skip to content

Instantly share code, notes, and snippets.

@garveen
Last active April 4, 2022 17:56
Show Gist options
  • Save garveen/336b248c2e07632be5d3 to your computer and use it in GitHub Desktop.
Save garveen/336b248c2e07632be5d3 to your computer and use it in GitHub Desktop.
using html 5 APIs, slice big file into blob and upload
<?php
/*
you may modify:
php:
filename
file max size
buf size
how long to wait
javascript:
max_retry
block_size
max_threads
*/
if (isset($_FILES['blob'])) {
header('content-type:application/json');
if (!is_dir('upload')) {
mkdir('upload');
}
$start = $_POST['start'];
// you may hash the filename
$filename = 'upload/' . $_POST['filename'];
$count = 0;
while ($start != 0 && !file_exists($filename)) {
$count++;
if ($count > 20) {
// after 1 seconds
echo json_encode(array('status' => false));
exit;
}
usleep(50000);
}
if ($start == 0) {
$desc = fopen($filename, 'c');
// you may decide the max size
ftruncate($desc, $_POST['size']);
} else {
for ($count = 0;; $count++) {
if (filesize($filename) == 0) {
if ($count > 20) {
// after 1 seconds
echo json_encode(array('status' => false));
exit;
}
usleep(50000);
clearstatcache(false, $filename);
} else {
$desc = fopen($filename, 'r+');
break;
}
}
}
fseek($desc, $start);
$src = fopen($_FILES['blob']['tmp_name'], 'r');
while (!feof($src)) {
$buf = fread($src, 4194304); //4M
fwrite($desc, $buf);
}
fclose($src);
fclose($desc);
echo json_encode(array('status' => true, 'block' => $_POST['block']));
}
<script src='//code.jquery.com/jquery-1.10.2.min.js'></script>
<input type='file' id='file' />
<input type='button' value='send' id='send'>
<script>
var max_retry = 5;
var block_size = 4194304;
var max_threads = 4;
var curr_threads = 0;
var logs = [];
var stack = [];
var intervalId = null;
var check = function() {
var status = true;
$.each(logs, function(index, value) {
if(!value) {
status = false;
return false;
}
})
if(status) {
clearInterval(intervalId);
alert('success');
}
}
var upload = function(){
var result = [];
var resultCount = 0;
var file = $('#file')[0].files[0];
var max = Math.ceil(file.size / block_size);
//must twice
for(i = 0; i < max; i++) {
logs[i] = false;
}
for(i = 0; i < max; i++ ) {
pushAjax(file, i, 0);
}
intervalId = setInterval(loopAjax, 10);
}
var sendAjax = function(file, index, retry) {
curr_threads++;
if(retry > max_retry) {
alert('failed');
return;
}
var blob = file.slice(block_size * index, block_size * (index + 1));
var fd = new FormData();
fd.append('filename', file.name);
fd.append('start', block_size * index);
fd.append('size', file.size);
fd.append('block', index);
fd.append('blob', blob);
fd.append('retry', retry);
$.ajax({
type: 'post',
data: fd,
processData: false,
contentType: false,
dataType: 'json',
url:'bigfileUpload.php',
success: function(data) {
curr_threads--;
if(!data.status) {
pushAjax(file, index, retry + 1);
} else {
logs[data.block] = true;
check();
}
},
error: function() {
curr_threads--;
pushAjax(file, index, retry + 1);
}
})
}
var pushAjax = function(file, index, retry) {
stack.push([file, index, retry]);
}
var loopAjax = function() {
if(curr_threads < max_threads) {
var arr = stack.shift();
if(typeof arr != 'undefined') {
sendAjax(arr[0], arr[1], arr[2]);
}
}
}
$('#send').click(upload);
</script>
@Akhlys
Copy link

Akhlys commented Nov 11, 2020

Thanks, worked like a charm.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment