p2 project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

361 lines
15 KiB

5 months ago
<?php
namespace app\admin\controller;
use app\model\AwsS3Model;
use app\model\FileModel;
2 months ago
use app\utility\AwsS3Handler;
5 months ago
use Aws\S3\S3Client;
use think\facade\Filesystem;
use think\facade\Config;
3 months ago
use think\facade\Log;
5 months ago
class Upload extends AdminBaseController
{
2 months ago
// 上传文件至服务器本地
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]]);
}
// 上传图片至 aws s3
public function uploadImg()
5 months ago
{
try {
// 获取文件
$file = $this->request->file('file');
4 months ago
// 检测文件是否存在
if (!$file) {
return json(['code' => 400, 'message' => 'No file uploaded']);
}
3 months ago
// 验证文件类型和大小, 限制20M
$maxSize = 20 * 1024 * 1024;
4 months ago
if ($file->getSize() > $maxSize) {
return json(['code' => 400, 'message' => 'Upload file is too large']);
}
3 months ago
// 打开文件
$openFile = fopen($file->getRealPath(), 'r');
if (!$openFile) {
return json(['code' => 400, 'message' => 'Failed to open the file']);
}
4 months ago
// 验证上传文件类型
if (!in_array($file->getOriginalMime(), ['image/jpeg','image/png','image/webp','image/bm'])) {
return json(['code' => 400, 'message' => 'Upload file type error']);
}
// 生成唯一的文件名
$fileName = bin2hex(random_bytes(16)) . '.' . $file->getOriginalExtension();
// 初始化s3客户端
$s3Config = Config::get('common.aws_s3');
2 months ago
$s3Obj = new AwsS3Handler($s3Config);
$keyName = 'bourse-avatar/' . $fileName;
$result = $s3Obj->putObject($keyName, $openFile, $file->getOriginalMime());
fclose($openFile);
if (!isset($result['data']['ObjectURL'])) {
return json(['code' => 400, 'message' => '上传图片至s3失败']);
5 months ago
}
4 months ago
// 记录上传的文件
2 months ago
AwsS3Model::create([
4 months ago
'name' => $fileName,
2 months ago
's3_url' => $result['data']['ObjectURL'],
4 months ago
'size' => $file->getSize(),
'mime' => $file->getOriginalMime(),
'ext' => $file->getOriginalExtension(),
]);
2 months ago
return json(['code' => '0', 'message' => '上传成功', 'data' => ['path' => $result['data']['ObjectURL']]]);
5 months ago
} catch (\Exception $exception) {
3 months ago
if (isset($openFile)) {
fclose($openFile);
}
3 months ago
return json(['code' => '500', 'message' => '系统繁忙', 'data' => [$exception->getMessage()]]);
5 months ago
}
}
2 months ago
// 上传视频到 aws s3
5 months ago
public function uploadVideo()
{
try {
// 获取文件
$file = $this->request->file('file');
// 检测文件是否存在
if (!$file) {
return json(['code' => 400, 'message' => 'No file uploaded']);
}
3 months ago
// 验证文件类型和大小 限制100M
$maxSize = 100 * 1024 * 1024;
5 months ago
if ($file->getSize() > $maxSize) {
return json(['code' => 400, 'message' => 'The file size cannot exceed 1 GB']);
}
3 months ago
// 打开文件
$openFile = fopen($file->getRealPath(), 'r');
if (!$openFile) {
return json(['code' => 400, 'message' => 'Failed to open the file']);
}
5 months ago
// 生成唯一的文件名
4 months ago
$fileName = bin2hex(random_bytes(16)) . '.' . $file->getOriginalExtension();
5 months ago
// 初始化s3客户端
$s3Config = Config::get('common.aws_s3');
2 months ago
$s3Obj = new AwsS3Handler($s3Config);
$keyName = 'bourse-video-node/' . $fileName;
$result = $s3Obj->putObject($keyName, $openFile, $file->getOriginalMime());
3 months ago
fclose($openFile);
Log::info("上传s3结果:". json_encode($result));
2 months ago
if (!isset($result['data']['ObjectURL'])) {
return json(['code' => 400, 'message' => '上传视频至s3失败']);
4 months ago
}
5 months ago
// 记录上传的文件
$resData = AwsS3Model::create([
'name' => $fileName,
2 months ago
's3_url' => $result['data']['ObjectURL'],
5 months ago
'size' => $file->getSize(),
'mime' => $file->getOriginalMime(),
'ext' => $file->getOriginalExtension(),
4 months ago
]);
5 months ago
// 返回上传成功的地址
return json(['code' => '0', 'message' => '上传成功', 'data' => [
'id' => $resData->id,
2 months ago
'url' => $result['data']['ObjectURL'],
5 months ago
'name' => $fileName,
'size' => $file->getSize(),
'mime' => $file->getOriginalMime(),
'ext'=> $file->getOriginalExtension(),
]]);
} catch (\Exception $exception) {
3 months ago
return json(['code' => '500', 'message' => '系统繁忙', 'data' => [$exception->getMessage()]]);
5 months ago
}
}
3 months ago
// 创建分段上传,初始化一个新的上传任务,生成一个上传的唯一标识符
5 months ago
public function initiateUpload(){
try {
3 months ago
$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' => '提取文件扩展名错误']);
5 months ago
}
// 生成唯一的文件名
3 months ago
$fileName = bin2hex(random_bytes(16)) . '.' . $getExt;
5 months ago
// 初始化s3客户端
$s3Config = Config::get('common.aws_s3');
$s3Client = new S3Client([
'version' => 'latest',
'region' => $s3Config['aws_region'],
'credentials' => [
'key' => $s3Config['aws_key'],
'secret' => $s3Config['aws_secret'],
],
]);
3 months ago
// 初始化分段上传,获取上传Id
5 months ago
$result = $s3Client->createMultipartUpload([
'Bucket' => $s3Config['aws_bucket'],
'Key' => 'bourse-video-node/' . $fileName,
3 months ago
'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,
3 months ago
'parts' => '',
3 months ago
'name' => $fileName,
'mime' => $getMime,
'ext' => $getExt,
5 months ago
]);
3 months ago
5 months ago
return json([
'code' => 0,
3 months ago
'message' => 'success',
5 months ago
'data' => [
'uploadId' => $result['UploadId'],
'key' => $result['Key']
]
]);
} catch (\Exception $exception) {
3 months ago
return json(['code' => '500', 'message' => '初始化分段上传失败', 'data' => [$exception->getMessage()]]);
5 months ago
}
}
3 months ago
// 上传每个分段
5 months ago
public function uploadPart(){
try {
$param = $this->request->param();
3 months ago
if (empty($param['uploadId']) || empty($param['partNumber'])) {
5 months ago
return json(['code' => 400, 'message' => '缺少参数']);
}
$file = $this->request->file('file');
if (!$file) {
return json(['code' => 400, 'message' => 'No file uploaded']);
}
3 months ago
// 每个分段大小限制 最大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']);
}
3 months ago
// 检查数据库中是否有对应上传记录
$awsS3 = AwsS3Model::where(['upload_id'=>$param['uploadId']])->find();
if (empty($awsS3) || empty($awsS3['key'])) {
return json(['code' => 400, 'message' => 'uploadId对应的数据错误']);
}
5 months ago
// 初始化s3客户端
$s3Config = Config::get('common.aws_s3');
$s3Client = new S3Client([
'version' => 'latest',
'region' => $s3Config['aws_region'],
'credentials' => [
'key' => $s3Config['aws_key'],
'secret' => $s3Config['aws_secret'],
],
]);
$result = $s3Client->uploadPart([
'Bucket' => $s3Config['aws_bucket'],
3 months ago
'Key' => $awsS3['key'],
5 months ago
'PartNumber' => $param['partNumber'],
'UploadId' => $param['uploadId'],
3 months ago
'Body' => $openFile,
])->toArray();
fclose($openFile);
Log::info("上传分段结果:".json_encode($result));
3 months ago
if (empty($result['ETag'])) {
3 months ago
return json(['code' => 400, 'message' => '上传分片失败']);
}
// 更新上传分片记录
if (empty($awsS3->parts)) {
$buildParts = json_encode([
['PartNumber'=>trim($param['partNumber']), 'ETag'=>$result['ETag']]
]);
$awsS3->parts = $buildParts;
} else {
$parsePart = json_decode($awsS3->parts, true);
$parsePart[] = ['PartNumber'=>trim($param['partNumber']), 'ETag'=>$result['ETag']];
$awsS3->parts = json_encode($parsePart);
}
$awsS3->save();
5 months ago
return json([
'code' => 200,
3 months ago
'message' => 'success',
5 months ago
'data' => [
3 months ago
'ETag' => $result['ETag'], // 每个分段的ETag
'PartNumber' => $param['partNumber'],
'key' => $param['key'], // 存储在s3桶中的key
5 months ago
]
]);
} catch (\Exception $exception) {
3 months ago
if (isset($openFile)) {
fclose($openFile);
}
3 months ago
return json(['code' => '500', 'message' => '上传失败', 'data' => [$exception->getMessage()]]);
5 months ago
}
}
3 months ago
// 完成分段上传
5 months ago
public function completeUpload(){
try {
$param = $this->request->param();
3 months ago
if (empty($param['uploadId'])) {
5 months ago
return json(['code' => 400, 'message' => '缺少参数']);
}
3 months ago
// 注意:$parts 是一个数组,里面需要有每个分段编号,以及每个分段对应的ETag
// $parts = [
// ['PartNumber' => 1, 'ETag' => 'etag-for-part-1'],
// ['PartNumber' => 2, 'ETag' => 'etag-for-part-2'],
// ];
3 months ago
$awsS3 = AwsS3Model::where(['upload_id'=>trim($param['uploadId'])])->find();
if (empty($awsS3) || empty($awsS3['parts']) || empty($awsS3['key'])) {
return json(['code' => 400, 'message' => 'uploadId对应的数据错误']);
}
3 months ago
// 取出上传的分片记录,并排序
$parts = json_decode($awsS3['parts'],true);
$partNumbers = array_column($parts, 'PartNumber');
array_multisort($partNumbers, SORT_ASC, $parts);
3 months ago
5 months ago
// 初始化s3客户端
$s3Config = Config::get('common.aws_s3');
$s3Client = new S3Client([
'version' => 'latest',
'region' => $s3Config['aws_region'],
'credentials' => [
'key' => $s3Config['aws_key'],
'secret' => $s3Config['aws_secret'],
],
]);
3 months ago
$result = $s3Client->completeMultipartUpload([
5 months ago
'Bucket' => $s3Config['aws_bucket'],
3 months ago
'Key' => $awsS3['key'],
5 months ago
'UploadId' => $param['uploadId'],
'MultipartUpload' => [
3 months ago
'Parts' => $parts
5 months ago
],
3 months ago
])->toArray();
Log::info("完成分段上传结果:".json_encode($result));
5 months ago
3 months ago
// 更新分片上传记录
$awsS3->is_complete = 1;
$awsS3->s3_url = $result['Location'];
$awsS3->save();
3 months ago
return json([
'code' => 0,
'message' => '上传成功',
'data'=>[
'id' => $awsS3->id,
'uploadId' => $param['uploadId'],
'location' => $result['Location'],
]
]);
5 months ago
} catch (\Exception $exception) {
3 months ago
return json(['code' => '500', 'message' => '完成上传失败', 'data' => [$exception->getMessage()]]);
5 months ago
}
}
3 months ago
// 中止分段上传
5 months ago
public function abortUpload(){
try {
$param = $this->request->param();
if (empty($param['uploadId']) || empty($param['key'])) {
return json(['code' => 400, 'message' => '缺少参数']);
}
// 初始化s3客户端
$s3Config = Config::get('common.aws_s3');
$s3Client = new S3Client([
'version' => 'latest',
'region' => $s3Config['aws_region'],
'credentials' => [
'key' => $s3Config['aws_key'],
'secret' => $s3Config['aws_secret'],
],
]);
3 months ago
$result = $s3Client->abortMultipartUpload([
5 months ago
'Bucket' => $s3Config['aws_bucket'],
'Key' => $param['key'],
'UploadId' => $param['uploadId'],
]);
3 months ago
Log::info('终止分段上传结果:'.json_encode($result));
3 months ago
return json(['code' => 0, 'message' => '上传已取消']);
5 months ago
} catch (\Exception $exception) {
3 months ago
return json(['code' => '500', 'message' => '取消上传失败', 'data' => [$exception->getMessage()]]);
5 months ago
}
}
}