AdminOssUploadDownloadController.java 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package cc.uncarbon.module.oss.web;
  2. import cc.uncarbon.framework.core.constant.HelioConstant;
  3. import cc.uncarbon.framework.web.model.response.ApiResult;
  4. import cc.uncarbon.module.oss.facade.OssUploadDownloadFacade;
  5. import cc.uncarbon.module.oss.model.request.UploadFileAttributeDTO;
  6. import cc.uncarbon.module.oss.model.response.OssFileDownloadReplyBO;
  7. import cc.uncarbon.module.oss.model.response.OssFileInfoBO;
  8. import cc.uncarbon.module.oss.model.response.OssFileUploadResultVO;
  9. import cc.uncarbon.module.sys.constant.SysConstant;
  10. import cc.uncarbon.module.sys.util.AdminStpUtil;
  11. import cn.dev33.satoken.annotation.SaCheckLogin;
  12. import cn.hutool.core.io.IoUtil;
  13. import cn.hutool.core.util.CharsetUtil;
  14. import cn.hutool.core.util.ObjectUtil;
  15. import cn.hutool.core.util.StrUtil;
  16. import cn.hutool.crypto.digest.DigestUtil;
  17. import cn.hutool.http.Header;
  18. import io.swagger.annotations.Api;
  19. import io.swagger.annotations.ApiOperation;
  20. import lombok.RequiredArgsConstructor;
  21. import lombok.extern.slf4j.Slf4j;
  22. import org.springframework.http.MediaType;
  23. import org.springframework.web.bind.annotation.*;
  24. import org.springframework.web.multipart.MultipartFile;
  25. import javax.servlet.http.HttpServletRequest;
  26. import javax.servlet.http.HttpServletResponse;
  27. import javax.validation.Valid;
  28. import java.io.IOException;
  29. import java.net.URLEncoder;
  30. @RequiredArgsConstructor
  31. @Slf4j
  32. @Api(value = "后台管理-上传、下载文件接口", tags = {"后台管理-上传、下载文件接口"})
  33. @RequestMapping(SysConstant.SYS_MODULE_CONTEXT_PATH + HelioConstant.Version.HTTP_API_VERSION_V1 + "/oss/files")
  34. @RestController
  35. public class AdminOssUploadDownloadController {
  36. private final OssUploadDownloadFacade ossUploadDownloadFacade;
  37. @ApiOperation(value = "上传文件", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
  38. @PostMapping
  39. // 约束:登录后才能上传 👇 后台管理对应的鉴权工具类
  40. @SaCheckLogin(type = AdminStpUtil.TYPE)
  41. public ApiResult<OssFileUploadResultVO> upload(
  42. @RequestPart MultipartFile file, @RequestPart(required = false) @Valid UploadFileAttributeDTO attr,
  43. HttpServletRequest request
  44. ) throws IOException {
  45. /*
  46. 1. 已存在相同 MD5 文件,直接返回 URL
  47. */
  48. String md5 = DigestUtil.md5Hex(file.getBytes());
  49. OssFileInfoBO bo = ossUploadDownloadFacade.findByHash(md5);
  50. if (bo == null) {
  51. /*
  52. 2. 普通上传
  53. */
  54. attr = ObjectUtil.defaultIfNull(attr, UploadFileAttributeDTO::new);
  55. attr
  56. .setOriginalFilename(file.getOriginalFilename())
  57. .setContentType(file.getContentType())
  58. .setMd5(md5)
  59. ;
  60. bo = ossUploadDownloadFacade.upload(file.getBytes(), attr);
  61. }
  62. return ApiResult.data(this.toUploadResult(bo, request.getRequestURL().toString()));
  63. }
  64. @ApiOperation(value = "下载文件(根据文件ID)", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
  65. @GetMapping(value = "/{id}")
  66. // 如果需要登录后才能下载,请解禁下方注解;注意是👇 后台管理对应的鉴权工具类
  67. // @SaCheckLogin(type = AdminStpUtil.TYPE)
  68. public void download(@PathVariable Long id, HttpServletResponse response) throws IOException {
  69. OssFileDownloadReplyBO reply = ossUploadDownloadFacade.downloadById(id);
  70. if (reply.isRedirect2DirectUrl()) {
  71. // 302重定向
  72. response.sendRedirect(reply.getDirectUrl());
  73. return;
  74. }
  75. // 普通下载
  76. response.setHeader(Header.CONTENT_TYPE.getValue(), MediaType.APPLICATION_OCTET_STREAM_VALUE);
  77. response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
  78. String downFileName = URLEncoder.encode(reply.getStorageFilename(), CharsetUtil.UTF_8);
  79. response.setHeader(Header.CONTENT_DISPOSITION.getValue(), "attachment;filename=" + downFileName);
  80. IoUtil.write(response.getOutputStream(), false, reply.getFileBytes());
  81. }
  82. /**
  83. * 将 OssFileInfoBO 转换为 OssFileUploadResultVO
  84. */
  85. private OssFileUploadResultVO toUploadResult(OssFileInfoBO ossFileInfo, String requestUrl) {
  86. OssFileUploadResultVO ret = new OssFileUploadResultVO()
  87. .setFileId(ossFileInfo.getId())
  88. .setFilename(ossFileInfo.getStorageFilenameFull());
  89. /*
  90. 这里请根据实际业务性质调整
  91. 有的业务出于安全目的,上传后文件只能通过文件ID才能下载
  92. 有的业务没有限制,上传后文件完全可以直接通过对象存储直链下载
  93. 但本地存储又没有直链,只能通过文件ID;
  94. 默认地,此处按【本地存储or对象存储直链为空:通过文件ID下载;对象存储:通过对象存储直链下载】返回 url
  95. */
  96. if (
  97. ossUploadDownloadFacade.isLocalPlatform(ossFileInfo.getStoragePlatform())
  98. || StrUtil.isEmpty(ossFileInfo.getDirectUrl())
  99. ) {
  100. ret.setUrl(
  101. // 默认接口风格为 RESTful,下载即为最后拼接“/{文件ID}”
  102. String.format("%s/%s", requestUrl, ossFileInfo.getId())
  103. );
  104. } else {
  105. ret.setUrl(ossFileInfo.getDirectUrl());
  106. }
  107. return ret;
  108. }
  109. }