Skip to content

Instantly share code, notes, and snippets.

@nemoTyrant
Created November 2, 2017 08:17
Show Gist options
  • Select an option

  • Save nemoTyrant/6a82dbf674a44583c0f0c29d49a7e2d5 to your computer and use it in GitHub Desktop.

Select an option

Save nemoTyrant/6a82dbf674a44583c0f0c29d49a7e2d5 to your computer and use it in GitHub Desktop.
resumable.js server side code
<?php
// check if file chunk is already uploaded
Route::get('resumable', function () {
// Array
// (
// [_token] => xLPuoAptQyWm0FfyAXJSAY1Gxr3lTzJkL9ECt81c
// [resumableChunkNumber] => 1
// [resumableChunkSize] => 2097152
// [resumableCurrentChunkSize] => 90482
// [resumableTotalSize] => 90482
// [resumableType] => image/jpeg
// [resumableIdentifier] => 90482-dog1jpg
// [resumableFilename] => dog1.jpg
// [resumableRelativePath] => dog1.jpg
// [resumableTotalChunks] => 1
// )
$chunkNumber = Request::get('resumableChunkNumber');
$identifier = Request::get('resumableIdentifier');
$filename = "{$identifier}.part.{$chunkNumber}";
if (file_exists($filename)) {
Log::info("check for " . $filename . ': already uploaded');
return response('', 200);
} else {
Log::info("check for " . $filename . ': not exists');
return response('', 204);
}
});
// upload file chunk
Route::post('resumable', function () {
// Array
// (
// [resumableChunkNumber] => 1
// [resumableChunkSize] => 2097152
// [resumableCurrentChunkSize] => 90482
// [resumableTotalSize] => 90482
// [resumableType] => image/jpeg
// [resumableIdentifier] => 90482-dog1jpg
// [resumableFilename] => dog1.jpg
// [resumableRelativePath] => dog1.jpg
// [resumableTotalChunks] => 1
// [_token] => xLPuoAptQyWm0FfyAXJSAY1Gxr3lTzJkL9ECt81c
// [file] => Illuminate\Http\UploadedFile Object
// (
// [test:Symfony\Component\HttpFoundation\File\UploadedFile:private] =>
// [originalName:Symfony\Component\HttpFoundation\File\UploadedFile:private] => blob
// [mimeType:Symfony\Component\HttpFoundation\File\UploadedFile:private] => application/octet-stream
// [size:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 90482
// [error:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 0
// [hashName:protected] =>
// [pathName:SplFileInfo:private] => /private/var/tmp/phpqhptXb
// [fileName:SplFileInfo:private] => phpqhptXb
// )
//
// )
$chunkNumber = Request::get('resumableChunkNumber');
$identifier = Request::get('resumableIdentifier');
$totaleChunks = Request::get('resumableTotalChunks');
Log::info('request: ' . $chunkNumber, Request::all());
$filename = "{$identifier}.part.{$chunkNumber}";
Request::file('file')->move('./', $filename);
return response()->json(['success' => 'OK'], 200);
});
// concatenate all chunks. Because you can upload multiple chunks at the same time, you don't know when all chunks
// are uploaded. I add a new request in resumable.js's fileSuccess callback to tell server to concatenate chunks
Route::post('concatenate', function () {
$identifier = Request::get('identifier');
$chunks = Request::get('chunks');
$fileName = Request::get('fileName');
Log::info('concatenate file', Request::all());
$start = microtime(true);
// 1. make sure all parts exists
for ($i = 1; $i <= $chunks; $i++) {
$partName = "{$identifier}.part.{$i}";
if (file_exists($partName) == false) {
return ['res' => 1, 'msg' => 'file not exists'];
}
}
// 2. concatenate parts
$tmpName = $identifier . '.tmp';
$file = fopen($tmpName, 'wb');
for ($i = 1; $i <= $chunks; $i++) {
$partName = "{$identifier}.part.{$i}";
$partFile = fopen($partName, 'r');
while (!feof($partFile)) {
fwrite($file, fread($partFile, 4096));
}
fclose($partFile);
}
fclose($file);
rename($tmpName, $fileName);
for ($i = 1; $i <= $chunks; $i++) {
$partName = "{$identifier}.part.{$i}";
unlink($partName);
}
Log::info('memory for concatenating file: ' . memory_get_peak_usage(true));
Log::info('used time: ' . (microtime(true) - $start));
});
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment