-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7fa6e7e
commit a1e93ae
Showing
19 changed files
with
437 additions
and
185 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,19 @@ | ||
<?php | ||
|
||
use Illuminate\Routing\Router; | ||
use Illuminate\Support\Facades\Route; | ||
|
||
/* | ||
|-------------------------------------------------------------------------- | ||
| Chunk Upload Routes | ||
|-------------------------------------------------------------------------- | ||
| | ||
*/ | ||
|
||
Route::group([], function(Router $router){ | ||
|
||
$router->get('/example', function () { | ||
return view('chunk-upload::example'); | ||
}); | ||
|
||
Route::namespace('\ChunkUpload\Controllers')->group(function (Router $router) { | ||
// 上传预处理 | ||
$router->post('/preprocess', '\ChunkUpload\Controllers\UploadController@preprocess')->name('chunk-preprocess'); | ||
$router->post('/preprocess', 'UploadController@preprocess')->name('chunk-preprocess'); | ||
// 分块上传 | ||
$router->post('/uploading', '\ChunkUpload\Controllers\UploadController@uploading')->name('chunk-uploading'); | ||
|
||
}); | ||
$router->post('/uploading', 'UploadController@uploading')->name('chunk-uploading'); | ||
// 演示程序 | ||
$router->get('/show-upload-example', 'ExampleController@index'); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
|
||
namespace ChunkUpload; | ||
|
||
use Illuminate\Http\JsonResponse; | ||
use Illuminate\Routing\Controller; | ||
|
||
class BaseController extends Controller | ||
{ | ||
public function responseJson($data = [], $status = 200, array $headers = [], $options = 0): JsonResponse | ||
{ | ||
is_string($data) && $data = ['message' => $data]; | ||
return response()->json($data, $status, $headers, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?php | ||
|
||
namespace ChunkUpload\Controllers; | ||
|
||
use ChunkUpload\BaseController; | ||
|
||
class ExampleController extends BaseController | ||
{ | ||
public function index() | ||
{ | ||
return view('chunk-upload::example'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,142 +1,71 @@ | ||
<?php | ||
|
||
namespace ChunkUpload\Controllers; | ||
|
||
use App\Http\Controllers\Controller; | ||
use Illuminate\Http\Request; | ||
use OSS\OssClient; | ||
use ChunkUpload\BaseController; | ||
use ChunkUpload\MultipartUpload; | ||
use ChunkUpload\Requests\PartUploadRequest; | ||
use ChunkUpload\Requests\PreprocessRequest; | ||
use Illuminate\Http\JsonResponse; | ||
use Illuminate\Support\Facades\Cache; | ||
|
||
class UploadController extends Controller | ||
class UploadController extends BaseController | ||
{ | ||
// OSS SDK 客户端 | ||
protected $ossClient; | ||
|
||
// 上传 Bucket | ||
protected $bucket; | ||
|
||
public function __construct() | ||
{ | ||
$access_id = config('chunk_upload.access_id'); | ||
$access_key = config('chunk_upload.access_key'); | ||
$endpoint_internal = config('chunk_upload.endpoint_internal'); | ||
$is_cdn = config('chunk_upload.is_cdn'); | ||
$this->bucket = config('chunk_upload.bucket'); | ||
$this->ossClient = new OssClient($access_id, $access_key, $endpoint_internal, $is_cdn); | ||
} | ||
|
||
/** | ||
* 大文件预处理,得到 UploadId 和 Pieces 信息 | ||
* @param PreprocessRequest $request | ||
* @param MultipartUpload $multipartUpload | ||
* @return JsonResponse | ||
*/ | ||
public function preprocess(Request $request) | ||
public function preprocess(PreprocessRequest $request, MultipartUpload $multipartUpload): JsonResponse | ||
{ | ||
$resource_name = $request->input('resource_name'); | ||
$resource_size = $request->input('resource_size', 0); | ||
$extension = explode('.', $resource_name); | ||
$resourceName = $request->input('resource_name'); | ||
$resourceSize = $request->input('resource_size', 0); | ||
$extension = explode('.', $resourceName); | ||
$extension = end($extension); | ||
|
||
$allow_extension = config('chunk_upload.allow_extension'); | ||
$allow_max_file_size = config('chunk_upload.allow_max_file_size'); | ||
$part_size = config('chunk_upload.part_size'); | ||
$allowExtension = config('chunk_upload.allow_extension'); | ||
$allowMaxFileSize = config('chunk_upload.allow_max_file_size'); | ||
$partSize = config('chunk_upload.part_size'); | ||
|
||
if (!in_array($extension, $allow_extension)) { | ||
// return $this->fail('不支持上传文件格式:' . $extension); | ||
if (!in_array($extension, $allowExtension)) { | ||
return $this->responseJson('不支持上传文件格式:' . $extension, 400); | ||
} | ||
if ($resource_size >= $allow_max_file_size) { | ||
// return $this->fail('文件大小超出限制:' . $allow_max_file_size); | ||
if ($resourceSize >= $allowMaxFileSize) { | ||
return $this->responseJson('文件大小超出限制:' . $allowMaxFileSize, 400); | ||
} | ||
$object = config('chunk_upload.upload_path') . DIRECTORY_SEPARATOR . uniqid() . DIRECTORY_SEPARATOR . $extension; | ||
// 初始化分块上传,得到 upload_id | ||
$upload_id = $this->ossClient->initiateMultipartUpload($this->bucket, $object); | ||
$pieces = $this->ossClient->generateMultiuploadParts($resource_size, $part_size); | ||
$filepath = config('chunk_upload.upload_path') . DIRECTORY_SEPARATOR . uniqid() . '.' . $extension; | ||
|
||
$uploadId = $multipartUpload->initiateUpload($filepath); | ||
$pieces = $multipartUpload->generateParts($resourceSize, $partSize); | ||
|
||
$data['object'] = $object; | ||
$data['upload_id'] = $upload_id; | ||
$data['part_size'] = $part_size; | ||
$data['file_path'] = $filepath; | ||
$data['upload_id'] = $uploadId; | ||
$data['part_size'] = $partSize; | ||
$data['extension'] = $extension; | ||
$data['resource_size'] = $resource_size; | ||
$data['resource_name'] = $resource_name; | ||
$data['resource_size'] = $resourceSize; | ||
$data['resource_name'] = $resourceName; | ||
$data['pieces'] = $pieces; | ||
$data['pieces_count'] = count($pieces); | ||
|
||
return response()->json($data, 200, [], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); | ||
Cache::put("{$uploadId}_preprocess", $data); | ||
return $this->responseJson($data); | ||
} | ||
|
||
/** | ||
* 分片上传处理 | ||
* @param PartUploadRequest $request | ||
* @param MultipartUpload $multipartUpload | ||
* @return JsonResponse|void | ||
*/ | ||
public function uploading(Request $request) | ||
{ | ||
$chunk_file = $request->file('chunk_file'); | ||
$part_index = $request->input('part_index'); | ||
$chunk_count = $request->input('chunk_count'); | ||
// 分块所属文件对象 | ||
$object = $request->input('oss_object'); | ||
// 分块所属 upload_id | ||
$upload_id = $request->input('upload_id'); | ||
// 历史分块标签 Tags | ||
$parts = $request->input('parts', ''); | ||
|
||
$options = array( | ||
$this->ossClient::OSS_FILE_UPLOAD => $chunk_file->getRealPath(), | ||
$this->ossClient::OSS_PART_NUM => $part_index, | ||
$this->ossClient::OSS_SEEK_TO => 0, | ||
$this->ossClient::OSS_LENGTH => filesize($chunk_file->getRealPath()) - 1, | ||
$this->ossClient::OSS_CHECK_MD5 => false, | ||
); | ||
|
||
try { | ||
// upload_part 是由每个分片的 ETag 和 分片号(PartNumber)组成的数组。 | ||
$res_upload_part = $this->ossClient->uploadPart($this->bucket, $object, $upload_id, $options); | ||
} catch (OssException $e) { | ||
printf($e->getMessage() . "\n"); | ||
return; | ||
} | ||
|
||
$result = ['part_index' => $part_index, 'chunk_count' => $chunk_count, 'part' => $res_upload_part]; | ||
// 是否完成所有分片上传 | ||
if ($part_index >= $chunk_count) { | ||
// 组装所有分块 Tags 信息 | ||
$part_arr = explode(',', $parts); | ||
$upload_parts = array(); | ||
$index = 1; | ||
foreach ($part_arr as $part) { | ||
if (!empty($part)) { | ||
$upload_parts[] = array( | ||
'PartNumber' => $index++, | ||
'ETag' => $part, | ||
); | ||
} | ||
} | ||
// 最后一个完成上传的分块 | ||
$upload_parts[] = array( | ||
'PartNumber' => $index, | ||
'ETag' => $res_upload_part, | ||
); | ||
try { | ||
$this->ossClient->completeMultipartUpload($this->bucket, $object, $upload_id, $upload_parts); | ||
$result['resource'] = $object; | ||
} catch (OssException $e) { | ||
printf($e->getMessage() . "\n"); | ||
return; | ||
} | ||
} | ||
return response()->json($result, 200, [], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); | ||
} | ||
|
||
/** | ||
* 取消上传 | ||
*/ | ||
public function abortUpload() | ||
public function uploading(PartUploadRequest $request, MultipartUpload $multipartUpload): JsonResponse | ||
{ | ||
// todo | ||
// try{ | ||
// $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint); | ||
$partFile = $request->file('chunk_file'); | ||
$uploadId = $request->input('upload_id'); | ||
$partIndex = $request->input('part_index'); | ||
|
||
// $ossClient->abortMultipartUpload($bucket, $object, $upload_id); | ||
// } catch(OssException $e) { | ||
// printf(__FUNCTION__ . ": FAILED\n"); | ||
// printf($e->getMessage() . "\n"); | ||
// return; | ||
// } | ||
$preprocess = Cache::get("{$uploadId}_preprocess"); | ||
$result = $multipartUpload->uploadPart($partFile, $partIndex, $preprocess['pieces_count'], $preprocess['file_path'], $uploadId); | ||
return $this->responseJson($result); | ||
} | ||
|
||
} |
Oops, something went wrong.