minio+tusd+uppy搭建文件上传服务

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-57Z
    container_name: minio-server
    restart: always
    hostname: minio
    ports:
    # API服务端口
      - 9100:9000
    # 管理系统端口
      - 9101:9001
    environment:
      # 管理系统用户名
      MINIO_ROOT_USER: admin
      # 管理系统密码
      MINIO_ROOT_PASSWORD: admin123
    volumes:
      - ./data:/data
      - ./config:/root/.minio/
    command: minio server --console-address ':9001'  /data
    privileged: true
    networks:
      - file-server

  tus-server:
    image: tusproject/tusd:2.0.0.rc21
    container_name: tus-server
    ports:
      - 9102:1080
    environment:
      # minio凭证,可以在minio管理系统生成key
      AWS_ACCESS_KEY_ID: admin
      AWS_SECRET_ACCESS_KEY: admin123
      AWS_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 -verbose
    privileged: true
    networks:
      - file-server

networks:
  file-server:
    driver: bridge
    ipam:
      config:
        - subnet: 155.119.0.0/16
          gateway: 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 * 1024

let uppy: Uppy

onMounted(() => {
  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 token
        const token = localStorage.getItem('test-token') as string
        req.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>

在这里插入图片描述
在这里插入图片描述

好的,以下是使用Minio和Spring Boot实现多级文件夹下的文件批量上传的代码: ``` import io.minio.MinioClient; import io.minio.errors.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @Service public class MinioService { @Autowired private MinioClient minioClient; @Value("${minio.bucket-name}") private String bucketName; public void uploadFiles(String parentFolder, MultipartFile[] files) throws IOException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, ServerException, InsufficientDataException, XmlParserException, InternalException, ErrorResponseException { for(MultipartFile file: files) { String fileName = file.getOriginalFilename(); String[] folders = parentFolder.split("/"); String folderPath = ""; for(String folder: folders) { if(!folder.isEmpty()) { folderPath += folder + "/"; if(!minioClient.bucketExists(bucketName + "/" + folderPath)) { minioClient.makeBucket(bucketName + "/" + folderPath); } } } minioClient.putObject(bucketName, parentFolder + "/" + fileName, file.getInputStream(), file.getSize(), file.getContentType()); } } } ``` 这里使用了Minio Java客户端来与Minio进行交互,通过`minioClient.bucketExists`方法判断是否存在该文件夹,如果不存在则创建,然后通过`minioClient.putObject`方法上传文件。 在application.properties文件中需要配置如下属性: ``` minio.endpoint=http://localhost:9000 minio.access-key=minio minio.secret-key=minio123 minio.bucket-name=my-bucket ``` 其中`minio.endpoint`为Minio服务的地址,`minio.access-key`和`minio.secret-key`为访问Minio服务的秘钥,`minio.bucket-name`为要上传到的桶的名称。 希望这个代码对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值