1、docker部署minio、tusd服務
1.1 新建docker-compose.yml
minio API: http://ip:9100
minio控制臺: http://ip:9101
tus API: http://ip:9102/files/
tus webhooh: http:172.0.0.1:3000/files/webhooh(用戶鑒權API)
version: '3.7'services:minio:image: minio/minio:RELEASE.2023-07-07T07-13-57Zcontainer_name: minio-serverrestart: alwayshostname: minioports:# API服務端口- 9100:9000# 管理系統端口- 9101:9001environment:# 管理系統用戶名MINIO_ROOT_USER: admin# 管理系統密碼MINIO_ROOT_PASSWORD: admin123volumes:- ./data:/data- ./config:/root/.minio/command: minio server --console-address ':9001' /dataprivileged: truenetworks:- file-servertus-server:image: tusproject/tusd:2.0.0.rc21container_name: tus-serverports:- 9102:1080environment:# minio憑證,可以在minio管理系統生成keyAWS_ACCESS_KEY_ID: adminAWS_SECRET_ACCESS_KEY: admin123AWS_REGION: eu-west-1# 配置minio地址、jwt鑒權地址,轉發headers字段command: -s3-bucket file-oos -s3-endpoint http://minio:9000 -hooks-http http:172.0.0.1:3000/files/webhooh -hooks-http-forward-headers Authorization -hooks-http-retry 3 -verboseprivileged: truenetworks:- file-servernetworks:file-server:driver: bridgeipam:config:- subnet: 155.119.0.0/16gateway: 155.119.0.1
1.2 啟動服務
docker-compose up -d
2、編寫鑒權接口,簡單點的話就校驗jwt token
import { Controller, Post, Req} from '@nestjs/common';
import { ApiTags, ApiOperation } from '@nestjs/swagger';@ApiTags('文件管理')
@Controller('files')
export class AuthController {@ApiOperation({ summary: 'tus服務鑒權' })@Post('webhooh')webhooh(@Req() request: Request) {/*** tus服務提供的鉤子* pre-create: 上傳請求創建前* post-create: 創建上傳請求* post-receive: 接收數據* post-finish: 上傳結束,可以在這里更改文件名*/const body: any = request.body;if (body.Type === 'post-finish') {const uploadData = body.Event.Upload;// 文件名和類型const { filename, filetype } = uploadData.MetaData;// minio桶名const bucket = uploadData.Storage.Bucket}return '鑒權通過';}
}
3、vue使用uppy上傳文件(支持多文件、斷點續傳、秒傳等)
<!-- 大文件上傳 -->
<template><div class="upload-container"><div id="uppy-dashboard"></div><!-- <div id="uppy-drag-drop"></div> --><!-- <div id="uppy-progress-bar"></div> --><!-- <div id="uppy-status-bar"></div> --></div>
</template><script setup lang="ts">
import { onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { locale } from './locale'
import Uppy from '@uppy/core'
// import DragDrop from '@uppy/drag-drop'
// import StatusBar from '@uppy/status-bar'
import Tus from '@uppy/tus'
import Dashboard from '@uppy/dashboard'
// import ProgressBar from '@uppy/progress-bar'//引入樣式
import '@uppy/core/dist/style.min.css'
import '@uppy/dashboard/dist/style.min.css'
import '@uppy/drag-drop/dist/style.min.css'
import '@uppy/progress-bar/dist/style.min.css'// 1mb大小
const ONE_MB = 1024 * 1024let uppy: UppyonMounted(() => {uppy = new Uppy({debug: true, // 允許拖拽autoProceed: false, // 是否自動上傳restrictions: {maxFileSize: 500 * ONE_MB, // 設置最大文件大小maxNumberOfFiles: 5, // 設置最大上傳文件數量allowedFileTypes: ['.jpg', '.jpeg', '.png', '.zip', '.webm'], // 設置允許的文件類型},}).use(Dashboard, {inline: true,target: '#uppy-dashboard',locale,waitForThumbnailsBeforeUpload: true, // 等待上傳之前的縮略圖showProgressDetails: true, // false: 百分比;true:百分比 + 剩余時間// note: '文件上傳', // 底部文案proudlyDisplayPoweredByUppy: false, // 隱藏底部的uppy文案})// .use(ProgressBar, { target: '#uppy-progress-bar' })// .use(DragDrop, { target: '#uppy-drag-drop', note: '拖放或點擊' }) // 啟用拖動// .use(StatusBar, { target: '#uppy-status-bar' }) //啟用進度條.use(Tus, {endpoint: 'http://127.0.0.1:9102/files/', // 設置上傳文件的API接口limit: 5, // 限制同時進行的上傳數量,默認值20,不要沒有限制或者過大chunkSize: 500 * ONE_MB, // 設置分片的大小allowedMetaFields: ['name', 'type'], // 上傳所有元數據async onBeforeRequest(req, file) {console.log(file)// 添加jwt tokenconst token = localStorage.getItem('test-token') as stringreq.setHeader('Authorization', token)},})uppy.on('files-added', (result: any) => {console.log('文件批量添加完成', result)})// 監聽文件上傳uppy.on('complete', (result: any) => {// result是一個對象,屬性是:// 會返回failed(Array),因為可以多文件上傳會返回一個數組// successful(Array),因為可以多文件上傳會返回一個數組,包含文件上傳成功的信息console.log('上傳完成:', result)if (Array.isArray(result.failed) && result.failed.length > 0) {ElMessage.error(`文件上傳失敗,${result.failed}`)} else {ElMessage.success(`文件上傳成功`)}})
})
</script>