|
|
@ -7,6 +7,7 @@ use app\model\FileModel; |
|
|
|
use Aws\S3\S3Client; |
|
|
|
use think\facade\Filesystem; |
|
|
|
use think\facade\Config; |
|
|
|
use think\facade\Log; |
|
|
|
|
|
|
|
class Upload extends AdminBaseController |
|
|
|
{ |
|
|
@ -20,11 +21,16 @@ class Upload extends AdminBaseController |
|
|
|
if (!$file) { |
|
|
|
return json(['code' => 400, 'message' => 'No file uploaded']); |
|
|
|
} |
|
|
|
// 验证文件类型和大小 |
|
|
|
$maxSize = 15 * 1024 * 1024; //限制M |
|
|
|
// 验证文件类型和大小, 限制20M |
|
|
|
$maxSize = 20 * 1024 * 1024; |
|
|
|
if ($file->getSize() > $maxSize) { |
|
|
|
return json(['code' => 400, 'message' => 'Upload file is too large']); |
|
|
|
} |
|
|
|
// 打开文件 |
|
|
|
$openFile = fopen($file->getRealPath(), 'r'); |
|
|
|
if (!$openFile) { |
|
|
|
return json(['code' => 400, 'message' => 'Failed to open the file']); |
|
|
|
} |
|
|
|
// 验证上传文件类型 |
|
|
|
if (!in_array($file->getOriginalMime(), ['image/jpeg','image/png','image/webp','image/bm'])) { |
|
|
|
return json(['code' => 400, 'message' => 'Upload file type error']); |
|
|
@ -45,10 +51,10 @@ class Upload extends AdminBaseController |
|
|
|
$result = $s3Client->putObject([ |
|
|
|
'Bucket' => $s3Config['aws_bucket'], |
|
|
|
'Key' => 'bourse-avatar/' . $fileName, // s3中的存储路径 |
|
|
|
'Body' => fopen($file->getRealPath(), 'r'), |
|
|
|
'Body' => $openFile, |
|
|
|
'ContentType' => $file->getOriginalMime(), // 设置文件的MIME, 不然s3会以流式存储 |
|
|
|
]); |
|
|
|
if (empty($result) || empty($result['ObjectURL'])) { |
|
|
|
])->toArray(); |
|
|
|
if (empty($result['ObjectURL'])) { |
|
|
|
return json(['code' => 400, 'message' => '上传s3失败']); |
|
|
|
} |
|
|
|
// 记录上传的文件 |
|
|
@ -59,10 +65,13 @@ class Upload extends AdminBaseController |
|
|
|
'mime' => $file->getOriginalMime(), |
|
|
|
'ext' => $file->getOriginalExtension(), |
|
|
|
]); |
|
|
|
|
|
|
|
fclose($openFile); |
|
|
|
// 返回路径 |
|
|
|
return json(['code' => '0', 'message' => '上传成功', 'data' => ['path' => $resData->s3_url]]); |
|
|
|
} catch (\Exception $exception) { |
|
|
|
if (isset($openFile)) { |
|
|
|
fclose($openFile); |
|
|
|
} |
|
|
|
return json(['code' => '100500', 'message' => '系统繁忙', 'data' => [$exception->getMessage()]]); |
|
|
|
} |
|
|
|
} |
|
|
@ -77,11 +86,16 @@ class Upload extends AdminBaseController |
|
|
|
if (!$file) { |
|
|
|
return json(['code' => 400, 'message' => 'No file uploaded']); |
|
|
|
} |
|
|
|
// 验证文件类型和大小 |
|
|
|
$maxSize = 1024 * 1024 * 1024; //限制1G |
|
|
|
// 验证文件类型和大小 限制100M |
|
|
|
$maxSize = 100 * 1024 * 1024; |
|
|
|
if ($file->getSize() > $maxSize) { |
|
|
|
return json(['code' => 400, 'message' => 'The file size cannot exceed 1 GB']); |
|
|
|
} |
|
|
|
// 打开文件 |
|
|
|
$openFile = fopen($file->getRealPath(), 'r'); |
|
|
|
if (!$openFile) { |
|
|
|
return json(['code' => 400, 'message' => 'Failed to open the file']); |
|
|
|
} |
|
|
|
// 生成唯一的文件名 |
|
|
|
$fileName = bin2hex(random_bytes(16)) . '.' . $file->getOriginalExtension(); |
|
|
|
// 初始化s3客户端 |
|
|
@ -99,12 +113,14 @@ class Upload extends AdminBaseController |
|
|
|
$result = $s3Client->putObject([ |
|
|
|
'Bucket' => $s3Config['aws_bucket'], |
|
|
|
'Key' => 'bourse-video-node/' . $fileName, // s3中的存储路径 |
|
|
|
'Body' => fopen($file->getRealPath(), 'r'), |
|
|
|
'Body' => $openFile, |
|
|
|
'ContentType' => $file->getOriginalMime(), // 设置文件的MIME, 不然s3会以流式存储 |
|
|
|
// 'ACL' => 'public-read', // 设置文件为公开可读 |
|
|
|
]); |
|
|
|
if (empty($result) || empty($result['ObjectURL'])) { |
|
|
|
return json(['code' => 400, 'message' => '上传s3失败']); |
|
|
|
])->toArray(); |
|
|
|
fclose($openFile); |
|
|
|
Log::info("上传s3结果:". json_encode($result)); |
|
|
|
if (empty($result['ObjectURL'])) { |
|
|
|
return json(['code' => 400, 'message' => '上传失败']); |
|
|
|
} |
|
|
|
// 记录上传的文件 |
|
|
|
$resData = AwsS3Model::create([ |
|
|
@ -124,30 +140,44 @@ class Upload extends AdminBaseController |
|
|
|
'ext'=> $file->getOriginalExtension(), |
|
|
|
]]); |
|
|
|
} catch (\Exception $exception) { |
|
|
|
if (isset($openFile)) { |
|
|
|
fclose($openFile); |
|
|
|
} |
|
|
|
return json(['code' => '100500', 'message' => '系统繁忙', 'data' => [$exception->getMessage()]]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 初始化分片上传 |
|
|
|
// 上传文件至服务器本地 |
|
|
|
public function uploadToServer() |
|
|
|
{ |
|
|
|
$file = $this->request->file('file'); |
|
|
|
if (!$file) { |
|
|
|
return json(['code' => 400, 'message' => 'No file uploaded233']); |
|
|
|
} |
|
|
|
if ($file->getSize() > 100 * 1024 * 1024) { |
|
|
|
return json(['code' => 400, 'message' => 'Upload file is too large']); |
|
|
|
} |
|
|
|
$name = Filesystem::disk('local')->putFile('topic', $file); |
|
|
|
$path = '/bs/image/'.$name; |
|
|
|
return json(['code'=>0, 'message'=>'ok', 'data'=>['path'=>$path]]); |
|
|
|
} |
|
|
|
|
|
|
|
// 创建分段上传,初始化一个新的上传任务,生成一个上传的唯一标识符 |
|
|
|
public function initiateUpload(){ |
|
|
|
try { |
|
|
|
$param = $this->request->param(); |
|
|
|
if (empty($param['file_type'])) { |
|
|
|
return json(['code' => '100500', 'message' => '缺少参数 file_type', 'data' => []]); |
|
|
|
} |
|
|
|
// 允许的视频类型 |
|
|
|
$allowed_types = [ |
|
|
|
'video/mp4', |
|
|
|
'video/quicktime', |
|
|
|
'video/x-msvideo', |
|
|
|
'video/x-ms-wmv', |
|
|
|
'video/x-matroska', |
|
|
|
]; |
|
|
|
if (!in_array($param['file_type'], $allowed_types)) { |
|
|
|
return json(['code' => '100500', 'message' => '上传的文件类型不在允许范围内', 'data' => []]); |
|
|
|
$param = $this->request->post(); |
|
|
|
if (empty($param['mime'])) { |
|
|
|
return json(['code' => 400, 'message' => '缺少参数mime']); |
|
|
|
} |
|
|
|
$getMime = trim($param['mime']); |
|
|
|
// 获取文件扩展名 |
|
|
|
$mimeArr = explode('/', $getMime); |
|
|
|
$getExt = end($mimeArr); |
|
|
|
if (empty($getExt)) { |
|
|
|
return json(['code' => 400, 'message' => '提取文件扩展名错误']); |
|
|
|
} |
|
|
|
// 生成唯一的文件名 |
|
|
|
$fileName = bin2hex(random_bytes(16)); |
|
|
|
$fileName = bin2hex(random_bytes(16)) . '.' . $getExt; |
|
|
|
// 初始化s3客户端 |
|
|
|
$s3Config = Config::get('common.aws_s3'); |
|
|
|
$s3Client = new S3Client([ |
|
|
@ -158,24 +188,38 @@ class Upload extends AdminBaseController |
|
|
|
'secret' => $s3Config['aws_secret'], |
|
|
|
], |
|
|
|
]); |
|
|
|
// 初始化Multipart Upload |
|
|
|
// 初始化分段上传,获取上传Id |
|
|
|
$result = $s3Client->createMultipartUpload([ |
|
|
|
'Bucket' => $s3Config['aws_bucket'], |
|
|
|
'Key' => 'bourse-video-node/' . $fileName, |
|
|
|
'ContentType' => $getMime, |
|
|
|
])->toArray(); |
|
|
|
Log::info("初始化分段上传结果:".json_encode($result)); |
|
|
|
if (empty($result['UploadId'])) { |
|
|
|
return json(['code' => 500, 'message' => '初始化分片上传失败','data'=>$result]); |
|
|
|
} |
|
|
|
AwsS3Model::create([ |
|
|
|
'upload_id' => $result['UploadId'], |
|
|
|
'key' => 'bourse-video-node/' . $fileName, |
|
|
|
'name' => $fileName, |
|
|
|
'mime' => $getMime, |
|
|
|
'ext' => $getExt, |
|
|
|
]); |
|
|
|
|
|
|
|
return json([ |
|
|
|
'code' => 0, |
|
|
|
'message' => 'success', |
|
|
|
'data' => [ |
|
|
|
'uploadId' => $result['UploadId'], |
|
|
|
'key' => $result['Key'] |
|
|
|
] |
|
|
|
]); |
|
|
|
} catch (\Exception $exception) { |
|
|
|
return json(['code' => '100500', 'message' => '初始化上传失败', 'data' => [$exception->getMessage()]]); |
|
|
|
return json(['code' => '500', 'message' => '初始化分段上传失败', 'data' => [$exception->getMessage()]]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 上传分片 |
|
|
|
// 上传每个分段 |
|
|
|
public function uploadPart(){ |
|
|
|
try { |
|
|
|
$param = $this->request->param(); |
|
|
@ -186,6 +230,15 @@ class Upload extends AdminBaseController |
|
|
|
if (!$file) { |
|
|
|
return json(['code' => 400, 'message' => 'No file uploaded']); |
|
|
|
} |
|
|
|
// 每个分段大小限制 最大50M |
|
|
|
if ($file->getSize() > 100 * 1024 * 1024) { |
|
|
|
return json(['code' => 400, 'message' => 'File size is too large for multipart upload']); |
|
|
|
} |
|
|
|
// 打开文件 |
|
|
|
$openFile = fopen($file->getRealPath(), 'r'); |
|
|
|
if (!$openFile) { |
|
|
|
return json(['code' => 400, 'message' => 'Failed to open file']); |
|
|
|
} |
|
|
|
// 初始化s3客户端 |
|
|
|
$s3Config = Config::get('common.aws_s3'); |
|
|
|
$s3Client = new S3Client([ |
|
|
@ -201,28 +254,43 @@ class Upload extends AdminBaseController |
|
|
|
'Key' => $param['key'], |
|
|
|
'PartNumber' => $param['partNumber'], |
|
|
|
'UploadId' => $param['uploadId'], |
|
|
|
'Body' => fopen($file->getRealPath(), 'r'), |
|
|
|
]); |
|
|
|
|
|
|
|
'Body' => $openFile, |
|
|
|
])->toArray(); |
|
|
|
fclose($openFile); |
|
|
|
Log::info("上传分段结果:".json_encode($result)); |
|
|
|
return json([ |
|
|
|
'code' => 200, |
|
|
|
'message' => 'success', |
|
|
|
'data' => [ |
|
|
|
'ETag' => $result['ETag'], |
|
|
|
'PartNumber' => $param['partNumber'] |
|
|
|
'ETag' => $result['ETag'], // 每个分段的ETag |
|
|
|
'PartNumber' => $param['partNumber'], |
|
|
|
'key' => $param['key'], // 存储在s3桶中的key |
|
|
|
] |
|
|
|
]); |
|
|
|
} catch (\Exception $exception) { |
|
|
|
if (isset($openFile)) { |
|
|
|
fclose($openFile); |
|
|
|
} |
|
|
|
return json(['code' => '100500', 'message' => '上传失败', 'data' => [$exception->getMessage()]]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 完成上传 |
|
|
|
// 完成分段上传 |
|
|
|
public function completeUpload(){ |
|
|
|
try { |
|
|
|
$param = $this->request->param(); |
|
|
|
if (empty($param['uploadId']) || empty($param['key']) || empty($param['parts'])) { |
|
|
|
if (empty($param['uploadId']) || empty($param['key'])) { |
|
|
|
return json(['code' => 400, 'message' => '缺少参数']); |
|
|
|
} |
|
|
|
if (empty($param['parts']) || !is_array($param['parts'])) { |
|
|
|
return json(['code' => 400, 'message' => 'parts参数错误']); |
|
|
|
} |
|
|
|
// 注意:$parts 是一个数组,里面需要有每个分段编号,以及每个分段对应的ETag |
|
|
|
// $parts = [ |
|
|
|
// ['PartNumber' => 1, 'ETag' => 'etag-for-part-1'], |
|
|
|
// ['PartNumber' => 2, 'ETag' => 'etag-for-part-2'], |
|
|
|
// ]; |
|
|
|
|
|
|
|
// 初始化s3客户端 |
|
|
|
$s3Config = Config::get('common.aws_s3'); |
|
|
|
$s3Client = new S3Client([ |
|
|
@ -233,22 +301,38 @@ class Upload extends AdminBaseController |
|
|
|
'secret' => $s3Config['aws_secret'], |
|
|
|
], |
|
|
|
]); |
|
|
|
$s3Client->completeMultipartUpload([ |
|
|
|
$result = $s3Client->completeMultipartUpload([ |
|
|
|
'Bucket' => $s3Config['aws_bucket'], |
|
|
|
'Key' => $param['key'], |
|
|
|
'UploadId' => $param['uploadId'], |
|
|
|
'MultipartUpload' => [ |
|
|
|
'Parts' => $param['parts'] |
|
|
|
], |
|
|
|
]); |
|
|
|
])->toArray(); |
|
|
|
Log::info("完成分段上传结果:".json_encode($result)); |
|
|
|
|
|
|
|
return json(['code' => 200, 'message' => '上传成功']); |
|
|
|
// 更新分片上传记录 |
|
|
|
$awsS3 = AwsS3Model::where(['upload_id'=>$param['uploadId']])->find(); |
|
|
|
if (empty($awsS3)) { |
|
|
|
return json(['code' => 500, 'message' => '数据记录错误']); |
|
|
|
} |
|
|
|
$awsS3->is_complete = 1; |
|
|
|
$awsS3->parts = json_encode($param['parts']); |
|
|
|
$awsS3->s3_url = $result['Location']; |
|
|
|
$awsS3->save(); |
|
|
|
|
|
|
|
return json(['code' => 200, 'message' => '上传成功', 'data'=>[ |
|
|
|
'id' => $awsS3->id, |
|
|
|
'uploadId' => $param['uploadId'], |
|
|
|
'key' => $param['key'], |
|
|
|
'location' => $result['Location'], |
|
|
|
]]); |
|
|
|
} catch (\Exception $exception) { |
|
|
|
return json(['code' => '100500', 'message' => '完成上传失败', 'data' => [$exception->getMessage()]]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 取消上传 |
|
|
|
// 中止分段上传 |
|
|
|
public function abortUpload(){ |
|
|
|
try { |
|
|
|
$param = $this->request->param(); |
|
|
@ -265,12 +349,12 @@ class Upload extends AdminBaseController |
|
|
|
'secret' => $s3Config['aws_secret'], |
|
|
|
], |
|
|
|
]); |
|
|
|
$s3Client->abortMultipartUpload([ |
|
|
|
$result = $s3Client->abortMultipartUpload([ |
|
|
|
'Bucket' => $s3Config['aws_bucket'], |
|
|
|
'Key' => $param['key'], |
|
|
|
'UploadId' => $param['uploadId'], |
|
|
|
]); |
|
|
|
|
|
|
|
Log::info('终止分段上传结果:'.json_encode($result)); |
|
|
|
return json(['code' => 200, 'message' => '上传已取消']); |
|
|
|
} catch (\Exception $exception) { |
|
|
|
return json(['code' => '100500', 'message' => '取消上传失败', 'data' => [$exception->getMessage()]]); |
|
|
|