TUS断点上传

使用tus将文件上传到minio中,并结合后端接口做token校验

使用Docker构建

Dockerfile

version: '3.3'
services:
  tus-server:
    image: tusio/tusd
    container_name: tus-server
    ports:
      - 1080:1080
    privileged: true
    environment:
      AWS_ACCESS_KEY_ID: minioadmin
      AWS_SECRET_ACCESS_KEY: minioadmin
      AWS_REGION: us-east-1
    command:
      ["--s3-bucket","bucketName","--s3-endpoint","http://192.168.10.39:9000","--base-path","/files/","--hooks-http-forward-headers","Authorization","--hooks-http","http://192.168.10.35:80/oss/tus-hooks","--hooks-enabled-events","pre-create,post-receive,pre-finish,post-finish"]
networks:
  default:
    driver: bridge

参数说明

  • --s3-bucket 对应的是bucket名称
  • --s3-endpoint 对应minIO的地址
  • --base-path tus的上传地址
  • --hooks-http-forward-headers 钩子回调时,需要转发的请求头,这边需要把业务方带的Authorization请求头转发给后端,用于鉴权
  • --hooks-http 钩子回调的后端地址,用于做一些中间操作,比如鉴权等
  • --hooks-enabled-events 哪些事件需要做回调,基本上是文件上传的一个生命周期内的回调事件。比如上传前,上传完成前,上传完成后等

启动服务

docker-compose up -d

定义后端钩子接口

伪代码逻辑

@PostMapping("/oss/tus-hooks")
public Result verify(HttpServletRequest request, @RequestBody Map<String, Object> map) {
    ossService.verify(request, map);
    return this.success();
}

public void verify(HttpServletRequest request, Map<String, Object> map) {
    String token = request.getHeader("Authorization");
    //校验token是否合法,伪代码,根据业务自定义
    Assert.isTrue(checkToken(token), "无权操作")
    String hookName = request.getHeader("hook-name");
    if ("post-finish".equals(hookName)) {
        //上传完成,得到文件信息,并存储到数据库中或者返回
        TusDTO tusDto = JSONUtil.toBean(JSONUtil.toJsonStr(map), TusDTO.class);
        save(tusDto);
    }
}

TusDTO的json格式

{
  "upload": {
    "id": "",
    "size": 0,
    "metaData": {
      "filename": "",
      "filetype": "",
      "name": "",
      "relativePath": "",
      "type": ""
    },
    "storage": {
      "bucket": "",
      "key": "",
      "type": ""
    }
  },
  "httpRequest": {
    "method": "",
    "uri": "",
    "remoteAddress": ""
  }
}

前端

使用Uppy.js断点上传

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Uppy</title>
    <link href="https://releases.transloadit.com/uppy/v2.3.2/uppy.min.css" rel="stylesheet">
  </head>
  <body>
    <div id="drag-drop-area"></div>
    <script src="https://releases.transloadit.com/uppy/v2.3.2/uppy.min.js"></script>
    <script>
      var uppy = new Uppy.Core()
        .use(Uppy.Dashboard, {
          inline: true,
          target: '#drag-drop-area'
        })
        // endpoint为tusdocker启动的接口地址 ,header中带上token
        .use(Uppy.Tus, {endpoint: 'http://10.66.38.175:1080/files/',headers:{
          "Authorization": "Bearer 1aed50be-d6a8-4b72-9ae9-3cba0e83cc0d"
        }})
      uppy.on('complete', (result) => {
        console.log('Upload complete! We’ve uploaded these files:', result.successful)
      })
    </script>
  </body>
</html>