文件上传、图片上传对接阿里云OSS

This commit is contained in:
柳清爽
2025-03-21 09:21:11 +08:00
parent 307096a509
commit cb67dd094b
5 changed files with 281 additions and 3 deletions

View File

@@ -13,4 +13,10 @@ Route::group('v1/auth', function () {
// 需要JWT认证的接口
Route::get('info', 'app\\common\\controller\\Auth@info')->middleware(['jwt']); // 获取用户信息
Route::post('refresh', 'app\\common\\controller\\Auth@refresh')->middleware(['jwt']); // 刷新令牌
});
});
// 附件上传相关路由
Route::group('v1/', function () {
Route::post('attachment/upload', 'app\\common\\controller\\Attachment@upload'); // 上传附件
Route::get('attachment/:id', 'app\\common\\controller\\Attachment@info'); // 获取附件信息
})->middleware(['jwt']);

View File

@@ -0,0 +1,140 @@
<?php
namespace app\common\controller;
use think\Controller;
use think\facade\Request;
use app\common\model\Attachment as AttachmentModel;
use app\common\util\AliyunOSS;
class Attachment extends Controller
{
/**
* 上传文件
* @return \think\response\Json
*/
public function upload()
{
try {
// 获取上传文件
$file = Request::file('file');
if (!$file) {
return json([
'code' => 400,
'msg' => '请选择要上传的文件'
]);
}
// 验证文件
$validate = \think\facade\Validate::rule([
'file' => [
'fileSize' => 10485760, // 10MB
'fileExt' => 'jpg,jpeg,png,gif,doc,docx,pdf,zip,rar',
'fileMime' => 'image/jpeg,image/png,image/gif,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/pdf,application/zip,application/x-rar-compressed'
]
]);
if (!$validate->check(['file' => $file])) {
return json([
'code' => 400,
'msg' => $validate->getError()
]);
}
// 生成文件hash
$hashKey = md5_file($file->getRealPath());
// 检查文件是否已存在
$existFile = AttachmentModel::getByHashKey($hashKey);
if ($existFile) {
return json([
'code' => 200,
'msg' => '文件已存在',
'data' => [
'id' => $existFile['id'],
'name' => $existFile['name'],
'url' => $existFile['source']
]
]);
}
// 生成OSS对象名称
$objectName = AliyunOSS::generateObjectName($file->getOriginalName());
// 上传到OSS
$result = AliyunOSS::uploadFile($file->getRealPath(), $objectName);
if (!$result['success']) {
return json([
'code' => 500,
'msg' => '文件上传失败:' . $result['error']
]);
}
// 保存到数据库
$attachmentData = [
'name' => Request::param('name') ?: $file->getOriginalName(),
'hash_key' => $hashKey,
'server' => 'aliyun_oss',
'source' => $result['url'],
'size' => $result['size'],
'suffix' => pathinfo($file->getOriginalName(), PATHINFO_EXTENSION)
];
$attachmentId = AttachmentModel::addAttachment($attachmentData);
if (!$attachmentId) {
return json([
'code' => 500,
'msg' => '保存附件信息失败'
]);
}
return json([
'code' => 200,
'msg' => '上传成功',
'data' => [
'id' => $attachmentId,
'name' => $attachmentData['name'],
'url' => $attachmentData['source']
]
]);
} catch (\Exception $e) {
return json([
'code' => 500,
'msg' => '上传失败:' . $e->getMessage()
]);
}
}
/**
* 获取附件信息
* @param int $id 附件ID
* @return \think\response\Json
*/
public function info($id)
{
try {
$attachment = AttachmentModel::find($id);
if (!$attachment) {
return json([
'code' => 404,
'msg' => '附件不存在'
]);
}
return json([
'code' => 200,
'msg' => '获取成功',
'data' => $attachment
]);
} catch (\Exception $e) {
return json([
'code' => 500,
'msg' => '获取失败:' . $e->getMessage()
]);
}
}
}

View File

@@ -0,0 +1,55 @@
<?php
namespace app\common\model;
use think\Model;
class Attachment extends Model
{
// 设置表名
protected $name = 'attachments';
// 设置主键
protected $pk = 'id';
// 自动写入时间戳
protected $autoWriteTimestamp = 'datetime';
// 定义时间戳字段名
protected $createTime = 'create_at';
protected $updateTime = 'update_at';
protected $deleteTime = 'delete_at';
// 定义字段类型
protected $type = [
'id' => 'integer',
'dl_count' => 'integer',
'size' => 'integer',
'scene' => 'integer',
'create_at' => 'datetime',
'update_at' => 'datetime',
'delete_at' => 'datetime'
];
/**
* 添加附件记录
* @param array $data 附件数据
* @return int|bool
*/
public static function addAttachment($data)
{
$attachment = new self();
return $attachment->allowField(true)->save($data);
}
/**
* 根据hash_key获取附件
* @param string $hashKey
* @return array|null
*/
public static function getByHashKey($hashKey)
{
return self::where('hash_key', $hashKey)
->where('delete_at', null)
->find();
}
}

View File

@@ -0,0 +1,77 @@
<?php
namespace app\common\util;
use OSS\OssClient;
use OSS\Core\OssException;
class AliyunOSS
{
// OSS配置信息
const ACCESS_KEY_ID = 'your_access_key_id';
const ACCESS_KEY_SECRET = 'your_access_key_secret';
const ENDPOINT = 'oss-cn-hangzhou.aliyuncs.com';
const BUCKET = 'your_bucket_name';
/**
* 获取OSS客户端实例
* @return OssClient
* @throws OssException
*/
public static function getClient()
{
try {
return new OssClient(
self::ACCESS_KEY_ID,
self::ACCESS_KEY_SECRET,
self::ENDPOINT
);
} catch (OssException $e) {
throw new OssException('创建OSS客户端失败' . $e->getMessage());
}
}
/**
* 上传文件到OSS
* @param string $filePath 本地文件路径
* @param string $objectName OSS对象名称
* @return array
* @throws OssException
*/
public static function uploadFile($filePath, $objectName)
{
try {
$client = self::getClient();
// 上传文件
$result = $client->uploadFile(self::BUCKET, $objectName, $filePath);
// 获取文件访问URL
$url = $client->signUrl(self::BUCKET, $objectName, 3600);
return [
'success' => true,
'url' => $url,
'object_name' => $objectName,
'size' => filesize($filePath),
'mime_type' => mime_content_type($filePath)
];
} catch (OssException $e) {
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
/**
* 生成OSS对象名称
* @param string $originalName 原始文件名
* @return string
*/
public static function generateObjectName($originalName)
{
$ext = pathinfo($originalName, PATHINFO_EXTENSION);
$name = md5(uniqid(mt_rand(), true));
return date('Y/m/d/') . $name . '.' . $ext;
}
}

View File

@@ -1,6 +1,6 @@
<?php
namespace app\common;
namespace app\common\util;
use Darabonba\OpenApi\Models\Config;
use AlibabaCloud\SDK\Dysmsapi\V20170525\Dysmsapi;
@@ -62,4 +62,4 @@ class AliyunSMS {
return FALSE;
}
}
}