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.
364 lines
15 KiB
364 lines
15 KiB
<?php
|
|
|
|
namespace app\admin\controller;
|
|
|
|
use app\model\AwsS3Model;
|
|
use app\model\FileModel;
|
|
use Aws\S3\S3Client;
|
|
use think\facade\Filesystem;
|
|
use think\facade\Config;
|
|
use think\facade\Log;
|
|
|
|
class Upload extends AdminBaseController
|
|
{
|
|
// 上传图片
|
|
public function upload()
|
|
{
|
|
try {
|
|
// 获取文件
|
|
$file = $this->request->file('file');
|
|
// 检测文件是否存在
|
|
if (!$file) {
|
|
return json(['code' => 400, 'message' => 'No file uploaded']);
|
|
}
|
|
// 验证文件类型和大小, 限制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']);
|
|
}
|
|
// 生成唯一的文件名
|
|
$fileName = bin2hex(random_bytes(16)) . '.' . $file->getOriginalExtension();
|
|
// 初始化s3客户端
|
|
$s3Config = Config::get('common.aws_s3');
|
|
$s3Client = new S3Client([
|
|
'version' => '2006-03-01',
|
|
'region' => $s3Config['aws_region'],
|
|
'credentials' => [
|
|
'key' => $s3Config['aws_key'],
|
|
'secret' => $s3Config['aws_secret'],
|
|
],
|
|
]);
|
|
// 上传文件到S3
|
|
$result = $s3Client->putObject([
|
|
'Bucket' => $s3Config['aws_bucket'],
|
|
'Key' => 'bourse-avatar/' . $fileName, // s3中的存储路径
|
|
'Body' => $openFile,
|
|
'ContentType' => $file->getOriginalMime(), // 设置文件的MIME, 不然s3会以流式存储
|
|
])->toArray();
|
|
if (empty($result['ObjectURL'])) {
|
|
return json(['code' => 400, 'message' => '上传s3失败']);
|
|
}
|
|
// 记录上传的文件
|
|
$resData = AwsS3Model::create([
|
|
'name' => $fileName,
|
|
's3_url' => $result['ObjectURL'],
|
|
'size' => $file->getSize(),
|
|
'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()]]);
|
|
}
|
|
}
|
|
|
|
// 上传视频到aws s3
|
|
public function uploadVideo()
|
|
{
|
|
try {
|
|
// 获取文件
|
|
$file = $this->request->file('file');
|
|
// 检测文件是否存在
|
|
if (!$file) {
|
|
return json(['code' => 400, 'message' => 'No file uploaded']);
|
|
}
|
|
// 验证文件类型和大小 限制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客户端
|
|
$s3Config = Config::get('common.aws_s3');
|
|
$s3Client = new S3Client([
|
|
// 'version' => 'latest',
|
|
'version' => '2006-03-01',
|
|
'region' => $s3Config['aws_region'],
|
|
'credentials' => [
|
|
'key' => $s3Config['aws_key'],
|
|
'secret' => $s3Config['aws_secret'],
|
|
],
|
|
]);
|
|
// 上传文件到S3
|
|
$result = $s3Client->putObject([
|
|
'Bucket' => $s3Config['aws_bucket'],
|
|
'Key' => 'bourse-video-node/' . $fileName, // s3中的存储路径
|
|
'Body' => $openFile,
|
|
'ContentType' => $file->getOriginalMime(), // 设置文件的MIME, 不然s3会以流式存储
|
|
// 'ACL' => 'public-read', // 设置文件为公开可读
|
|
])->toArray();
|
|
fclose($openFile);
|
|
Log::info("上传s3结果:". json_encode($result));
|
|
if (empty($result['ObjectURL'])) {
|
|
return json(['code' => 400, 'message' => '上传失败']);
|
|
}
|
|
// 记录上传的文件
|
|
$resData = AwsS3Model::create([
|
|
'name' => $fileName,
|
|
's3_url' => $result['ObjectURL'],
|
|
'size' => $file->getSize(),
|
|
'mime' => $file->getOriginalMime(),
|
|
'ext' => $file->getOriginalExtension(),
|
|
]);
|
|
// 返回上传成功的地址
|
|
return json(['code' => '0', 'message' => '上传成功', 'data' => [
|
|
'id' => $resData->id,
|
|
'url' => $result['ObjectURL'],
|
|
'name' => $fileName,
|
|
'size' => $file->getSize(),
|
|
'mime' => $file->getOriginalMime(),
|
|
'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->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)) . '.' . $getExt;
|
|
// 初始化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'],
|
|
],
|
|
]);
|
|
// 初始化分段上传,获取上传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' => '500', 'message' => '初始化分段上传失败', 'data' => [$exception->getMessage()]]);
|
|
}
|
|
}
|
|
|
|
// 上传每个分段
|
|
public function uploadPart(){
|
|
try {
|
|
$param = $this->request->param();
|
|
if (empty($param['uploadId']) || empty($param['key']) || empty($param['partNumber'])) {
|
|
return json(['code' => 400, 'message' => '缺少参数']);
|
|
}
|
|
$file = $this->request->file('file');
|
|
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([
|
|
'version' => 'latest',
|
|
'region' => $s3Config['aws_region'],
|
|
'credentials' => [
|
|
'key' => $s3Config['aws_key'],
|
|
'secret' => $s3Config['aws_secret'],
|
|
],
|
|
]);
|
|
$result = $s3Client->uploadPart([
|
|
'Bucket' => $s3Config['aws_bucket'],
|
|
'Key' => $param['key'],
|
|
'PartNumber' => $param['partNumber'],
|
|
'UploadId' => $param['uploadId'],
|
|
'Body' => $openFile,
|
|
])->toArray();
|
|
fclose($openFile);
|
|
Log::info("上传分段结果:".json_encode($result));
|
|
return json([
|
|
'code' => 200,
|
|
'message' => 'success',
|
|
'data' => [
|
|
'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'])) {
|
|
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([
|
|
'version' => 'latest',
|
|
'region' => $s3Config['aws_region'],
|
|
'credentials' => [
|
|
'key' => $s3Config['aws_key'],
|
|
'secret' => $s3Config['aws_secret'],
|
|
],
|
|
]);
|
|
$result = $s3Client->completeMultipartUpload([
|
|
'Bucket' => $s3Config['aws_bucket'],
|
|
'Key' => $param['key'],
|
|
'UploadId' => $param['uploadId'],
|
|
'MultipartUpload' => [
|
|
'Parts' => $param['parts']
|
|
],
|
|
])->toArray();
|
|
Log::info("完成分段上传结果:".json_encode($result));
|
|
|
|
// 更新分片上传记录
|
|
$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();
|
|
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'],
|
|
],
|
|
]);
|
|
$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()]]);
|
|
}
|
|
}
|
|
|
|
}
|