mirror of
https://github.com/Lastorder-DC/rhymix.git
synced 2026-01-08 19:21:40 +09:00
Implement chunked file uploads on the server side
This commit is contained in:
parent
ef27f8c0c4
commit
e2895912e5
1 changed files with 87 additions and 10 deletions
|
|
@ -29,21 +29,98 @@ class fileController extends file
|
|||
$file_info = $_FILES['Filedata'];
|
||||
|
||||
// An error appears if not a normally uploaded file
|
||||
if(!is_uploaded_file($file_info['tmp_name'])) exit();
|
||||
if(!$file_info || !is_uploaded_file($file_info['tmp_name'])) exit();
|
||||
|
||||
// Basic variables setting
|
||||
$oFileModel = getModel('file');
|
||||
$editor_sequence = Context::get('editor_sequence');
|
||||
$upload_target_srl = intval(Context::get('uploadTargetSrl'));
|
||||
if(!$upload_target_srl) $upload_target_srl = intval(Context::get('upload_target_srl'));
|
||||
$module_srl = $this->module_srl;
|
||||
|
||||
// Exit a session if there is neither upload permission nor information
|
||||
if(!$_SESSION['upload_info'][$editor_sequence]->enabled) exit();
|
||||
// Extract from session information if upload_target_srl is not specified
|
||||
if(!$upload_target_srl) $upload_target_srl = $_SESSION['upload_info'][$editor_sequence]->upload_target_srl;
|
||||
// Create if upload_target_srl is not defined in the session information
|
||||
if(!$upload_target_srl) $_SESSION['upload_info'][$editor_sequence]->upload_target_srl = $upload_target_srl = getNextSequence();
|
||||
|
||||
if(!$_SESSION['upload_info'][$editor_sequence]->enabled)
|
||||
{
|
||||
return new Object(-1, 'msg_not_permitted');
|
||||
}
|
||||
|
||||
// Get upload_target_srl
|
||||
$upload_target_srl = intval(Context::get('uploadTargetSrl')) ?: intval(Context::get('upload_target_srl'));
|
||||
if (!$upload_target_srl)
|
||||
{
|
||||
$upload_target_srl = $_SESSION['upload_info'][$editor_sequence]->upload_target_srl;
|
||||
}
|
||||
if (!$upload_target_srl)
|
||||
{
|
||||
$upload_target_srl = getNextSequence();
|
||||
$_SESSION['upload_info'][$editor_sequence]->upload_target_srl = $upload_target_srl;
|
||||
}
|
||||
|
||||
// Handle chunking
|
||||
if (preg_match('!^bytes (\d+)-(\d+)/(\d+)$!', $_SERVER['HTTP_CONTENT_RANGE'], $matches))
|
||||
{
|
||||
// Check basic sanity
|
||||
$chunk_start = $matches[1];
|
||||
$chunk_size = ($matches[2] - $matches[1]) + 1;
|
||||
$total_size = $matches[3];
|
||||
if ($chunk_start < 0 || $chunk_size < 0 || $total_size < 0 || $chunk_start + $chunk_size > $total_size || $chunk_size != $file_info['size'])
|
||||
{
|
||||
return new Object(-1, 'msg_upload_invalid_chunk');
|
||||
}
|
||||
|
||||
// Check existing chunks
|
||||
$temp_key = hash_hmac('sha1', sprintf('%d:%d:%d:%s', $editor_sequence, $upload_target_srl, $module_srl, $file_info['name']), config('crypto.authentication_key'));
|
||||
$temp_filename = RX_BASEDIR . 'files/attach/chunks/' . $temp_key;
|
||||
if ($chunk_start == 0 && Rhymix\Framework\Storage::isFile($temp_filename))
|
||||
{
|
||||
Rhymix\Framework\Storage::delete($temp_filename);
|
||||
return new Object(-1, 'msg_upload_invalid_chunk');
|
||||
}
|
||||
if ($chunk_start != 0 && (!Rhymix\Framework\Storage::isFile($temp_filename) || Rhymix\Framework\Storage::getSize($temp_filename) != $chunk_start))
|
||||
{
|
||||
Rhymix\Framework\Storage::delete($temp_filename);
|
||||
return new Object(-1, 'msg_upload_invalid_chunk');
|
||||
}
|
||||
|
||||
// Check size limit
|
||||
$is_admin = (Context::get('logged_info')->is_admin === 'Y');
|
||||
if (!$is_admin)
|
||||
{
|
||||
$module_config = getModel('file')->getFileConfig($module_srl);
|
||||
$allowed_attach_size = $module_config->allowed_attach_size * 1024 * 1024;
|
||||
$allowed_filesize = $module_config->allowed_filesize * 1024 * 1024;
|
||||
if ($total_size > $allowed_filesize)
|
||||
{
|
||||
return new Object(-1, 'msg_exceeds_limit_size');
|
||||
}
|
||||
$output = executeQuery('file.getAttachedFileSize', (object)array('upload_target_srl' => $upload_target_srl));
|
||||
if (intval($output->data->attached_size) + $total_size > $allowed_attach_size)
|
||||
{
|
||||
return new Object(-1, 'msg_exceeds_limit_size');
|
||||
}
|
||||
}
|
||||
|
||||
// Append to chunk
|
||||
$fp = fopen($file_info['tmp_name'], 'r');
|
||||
$success = Rhymix\Framework\Storage::write($temp_filename, $fp, 'a');
|
||||
if ($success && Rhymix\Framework\Storage::getSize($temp_filename) == $chunk_start + $chunk_size)
|
||||
{
|
||||
if ($chunk_start + $chunk_size == $total_size)
|
||||
{
|
||||
$file_info['tmp_name'] = $temp_filename;
|
||||
$file_info['size'] = Rhymix\Framework\Storage::getSize($temp_filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Rhymix\Framework\Storage::delete($temp_filename);
|
||||
return new Object(-1, 'msg_upload_chunk_append_failed');
|
||||
}
|
||||
}
|
||||
|
||||
// Save the file
|
||||
$output = $this->insertFile($file_info, $module_srl, $upload_target_srl);
|
||||
|
||||
Context::setResponseMethod('JSON');
|
||||
|
|
@ -752,7 +829,7 @@ class fileController extends file
|
|||
}
|
||||
|
||||
// Move the file
|
||||
if($manual_insert)
|
||||
if($manual_insert || starts_with(RX_BASEDIR . 'files/attach/chunks/', $file_info['tmp_name']))
|
||||
{
|
||||
@copy($file_info['tmp_name'], $filename);
|
||||
if(!file_exists($filename))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue