feat: 新增阿里 oss 上传组件

This commit is contained in:
JaguarJack 2023-02-21 17:16:52 +08:00
parent ef6a1204a9
commit 0351f61038
6 changed files with 205 additions and 2 deletions

View File

@ -58,3 +58,9 @@ VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
VITE_BASE_URL=${APP_URL}/api/ VITE_BASE_URL=${APP_URL}/api/
ALIOSS_BUCKET=
ALIOSS_ACCESS_ID=
ALIOSS_ACCESS_SECRET=
ALIOSS_ENDPOINT=
ALIOSS_UPLOAD_DIR=

View File

@ -3,6 +3,7 @@
namespace Modules\Common\Http\Controllers; namespace Modules\Common\Http\Controllers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Modules\Common\Support\Upload\OssUpload;
use Modules\Common\Support\Upload\Uploader; use Modules\Common\Support\Upload\Uploader;
/** /**
@ -31,4 +32,16 @@ class UploadController
{ {
return $uploader->upload($request->file('image')); return $uploader->upload($request->file('image'));
} }
/**
* oss upload
*
* @param OssUpload $ossUpload
* @return array
*/
public function oss(OssUpload $ossUpload): array
{
return $ossUpload->config();
}
} }

View File

@ -0,0 +1,101 @@
<?php
namespace Modules\Common\Support\Upload;
class OssUpload
{
/**
* @var string
*/
protected string $dir = 'upload/';
/**
* @var int
*/
protected int $expire = 30;
protected string $accessKeyId;
protected string $accessKeySecret;
protected string $endpoint;
protected int $maxSize;
protected string $bucket;
public function __construct()
{
$this->accessKeySecret = config('common.upload.oss.access_secret');
$this->accessKeyId = config('common.upload.oss.access_id');
$this->dir = date('Y-m-d') . '/';
$this->endpoint = config('common.upload.oss.endpoint');
$this->maxSize = config('common.upload.max_size');
$this->bucket = config('common.upload.oss.bucket');
}
/**
* config
*
* @return array
*/
public function config(): array
{
return [
'bucket' => $this->bucket,
'accessKeyId' => $this->accessKeyId,
'host' => sprintf('https://%s.%s', $this->bucket, $this->endpoint),
'policy' => $this->policy(),
'signature' => $this->signature(),
'expire' => $this->getExpiration(),
'dir' => $this->dir,
'url' => $this->endpoint . $this->dir
];
}
/**
*
* @return string
*/
protected function policy(): string
{
return base64_encode(json_encode([
'expiration' => $this->getExpiration(),
'conditions' => [
['starts-with', '$key', $this->dir],
['content-length-range', 0, $this->maxSize]
]
]));
}
/**
*
* @return string
*/
protected function signature(): string
{
return base64_encode(
\hash_hmac('sha1', $this->policy(), $this->accessKeySecret, true)
);
}
/**
*
* @return string
*/
protected function getExpiration(): string
{
return date('Y-m-d\TH:i:s\Z', time() + $this->expire);
}
}

View File

@ -0,0 +1,18 @@
<?php
return [
// 文件最大
'max_size' => 10 * 1024 * 1024,
// oss 配置
'oss' => [
'bucket' => env('ALIOSS_BUCKET'),
'access_id' => env('ALIOSS_ACCESS_ID'),
'access_secret' => env('ALIOSS_ACCESS_SECRET'),
'endpoint' => env('ALIOSS_ENDPOINT'),
'dir' => env('ALIOSS_UPLOAD_DIR')
],
];

View File

@ -17,6 +17,12 @@ use Modules\Common\Http\Controllers\UploadController;
Route::get('options/{name}', [OptionController::class, 'index']); Route::get('options/{name}', [OptionController::class, 'index']);
Route::post('upload/file', [UploadController::class, 'file']); Route::controller(UploadController::class)->group(function (){
Route::post('upload/file', 'file');
Route::post('upload/image', 'image');
// get oss signature
Route::get('upload/oss', 'oss');
});
Route::post('upload/image', [UploadController::class, 'image']);

View File

@ -0,0 +1,59 @@
<template>
<el-upload ref="upload" :action="action" :auto-upload="auto" v-bind="$attrs" :data="data" :before-upload="initOss" :on-success="handleSuccess">
<template v-for="(index, name) in $slots" v-slot:[name]>
<slot :name="name"></slot>
</template>
</el-upload>
</template>
<script setup lang="ts">
import http from "/admin/support/http"
import {ref} from "vue";
import Message from "/admin/support/message";
const props = defineProps({
auto: {
type: Boolean,
default: true,
},
modelValue: {
type: Boolean,
default: false,
require: true,
},
})
const action = ref('')
const data = ref({
OSSAccessKeyId: '',
policy: '',
Signature: '',
key: '',
host: '',
dir: '',
expire: '',
success_action_status: 200
})
const emits = defineEmits(['update:modelValue'])
const initOss = async (file) => {
if (file.size > 10 * 1024 * 1024) {
Message.error('最大支持 10MB 文件')
return
}
await http.get('upload/oss').then(r => {
const {accessKeyId, bucket, dir, expire, host, policy, signature, url} = r.data.data
action.value = host
data.value.OSSAccessKeyId = accessKeyId
data.value.policy = policy
data.value.Signature = signature
data.value.key = dir + file.name
data.value.host = host
data.value.dir = dir
data.value.expire = expire
})
}
const handleSuccess = (r) => {
emits('update:modelValue', action.value + data.value.key)
}
</script>