mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-09-18 17:38:48 +08:00
oss 文件操作
This commit is contained in:
parent
3d47accfeb
commit
552d9b4ca3
@ -0,0 +1,200 @@
|
|||||||
|
package com.luban.api.s3.ctrl;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.IoUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.liuxp.minioplus.api.StorageService;
|
||||||
|
import org.liuxp.minioplus.api.model.vo.CompleteResultVo;
|
||||||
|
import org.liuxp.minioplus.api.model.vo.FileCheckResultVo;
|
||||||
|
import org.liuxp.minioplus.api.model.vo.FilePreShardingVo;
|
||||||
|
import org.liuxp.minioplus.common.enums.MinioPlusErrorCode;
|
||||||
|
import org.liuxp.minioplus.common.enums.StorageBucketEnums;
|
||||||
|
import org.liuxp.minioplus.common.exception.MinioPlusException;
|
||||||
|
import org.liuxp.minioplus.extension.context.Response;
|
||||||
|
import org.liuxp.minioplus.extension.context.UserHolder;
|
||||||
|
import org.liuxp.minioplus.extension.dto.FileCheckDTO;
|
||||||
|
import org.liuxp.minioplus.extension.dto.FileCompleteDTO;
|
||||||
|
import org.liuxp.minioplus.extension.dto.PreShardingDTO;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.util.FileCopyUtils;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对象存储标准接口定义
|
||||||
|
* 本类的方法是给前端使用的方法
|
||||||
|
*
|
||||||
|
* @author contact@liuxp.me
|
||||||
|
* @since 2024/6/18
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("storage2")
|
||||||
|
public class Storage2Controller implements StorageWebAPI {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 存储引擎Service接口定义
|
||||||
|
*/
|
||||||
|
private final StorageService storageService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造方法
|
||||||
|
*
|
||||||
|
* @param storageService 注入存储引擎Service接口定义实现类
|
||||||
|
*/
|
||||||
|
public Storage2Controller(StorageService storageService) {
|
||||||
|
this.storageService = storageService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件预分片方法
|
||||||
|
* 在大文件上传时,为了防止前端重复计算文件MD5值,提供该方法
|
||||||
|
*
|
||||||
|
* @param preShardingDTO 文件预分片入参DTO
|
||||||
|
* @return 预分片结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Response<FilePreShardingVo> sharding(@RequestBody @Validated PreShardingDTO preShardingDTO) {
|
||||||
|
|
||||||
|
FilePreShardingVo resultVo = storageService.sharding(preShardingDTO.getFileSize());
|
||||||
|
|
||||||
|
return Response.success(resultVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传任务初始化
|
||||||
|
* 上传前的预检查:秒传、分块上传和断点续传等特性均基于该方法实现
|
||||||
|
*
|
||||||
|
* @param fileCheckDTO 文件预检查入参
|
||||||
|
* @return 检查结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Response<FileCheckResultVo> init(FileCheckDTO fileCheckDTO) {
|
||||||
|
|
||||||
|
// 取得当前登录用户信息
|
||||||
|
String userId = UserHolder.get();
|
||||||
|
|
||||||
|
FileCheckResultVo resultVo = storageService.init(fileCheckDTO.getFileMd5(), fileCheckDTO.getFullFileName(), fileCheckDTO.getFileSize(), fileCheckDTO.getIsPrivate(), userId);
|
||||||
|
|
||||||
|
return Response.success(resultVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件上传完成
|
||||||
|
*
|
||||||
|
* @param fileKey 文件KEY
|
||||||
|
* @param fileCompleteDTO 文件完成入参DTO
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Response<Object> complete(String fileKey, FileCompleteDTO fileCompleteDTO) {
|
||||||
|
|
||||||
|
// 取得当前登录用户信息
|
||||||
|
String userId = UserHolder.get();
|
||||||
|
|
||||||
|
// 打印调试日志
|
||||||
|
log.debug("合并文件开始fileKey=" + fileKey + ",partMd5List=" + fileCompleteDTO.getPartMd5List());
|
||||||
|
CompleteResultVo completeResultVo = storageService.complete(fileKey, fileCompleteDTO.getPartMd5List(), userId);
|
||||||
|
|
||||||
|
return Response.success(completeResultVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件下载
|
||||||
|
*
|
||||||
|
* @param fileKey 文件KEY
|
||||||
|
* @return 文件下载地址
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<Void> download(String fileKey) {
|
||||||
|
|
||||||
|
// 取得当前登录用户信息
|
||||||
|
String userId = UserHolder.get();
|
||||||
|
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setLocation(URI.create(storageService.download(fileKey, userId)));
|
||||||
|
return new ResponseEntity<>(headers, HttpStatus.SEE_OTHER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取图像
|
||||||
|
*
|
||||||
|
* @param fileKey 文件KEY
|
||||||
|
* @return 原图地址
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<Void> previewOriginal(String fileKey) {
|
||||||
|
|
||||||
|
// 取得当前登录用户信息
|
||||||
|
String userId = UserHolder.get();
|
||||||
|
|
||||||
|
// 取得文件读取路径
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setLocation(URI.create(storageService.download(fileKey, userId)));
|
||||||
|
return new ResponseEntity<>(headers, HttpStatus.SEE_OTHER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件预览
|
||||||
|
* 当文件为图片时,返回图片的缩略图
|
||||||
|
* 当文件不是图片时,返回文件类型图标
|
||||||
|
*
|
||||||
|
* @param fileKey 文件KEY
|
||||||
|
* @return 缩略图地址
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<Void> previewMedium(String fileKey) {
|
||||||
|
|
||||||
|
// 取得当前登录用户信息
|
||||||
|
String userId = UserHolder.get();
|
||||||
|
|
||||||
|
String url = storageService.preview(fileKey, userId);
|
||||||
|
if (url.length() < 10) {
|
||||||
|
// 当返回值为文件类型时,取得图标
|
||||||
|
url = ICON_PATH + url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取得文件读取路径
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setLocation(URI.create(url));
|
||||||
|
return new ResponseEntity<>(headers, HttpStatus.SEE_OTHER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据文件类型取得图标
|
||||||
|
*
|
||||||
|
* @param fileType 文件扩展名
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void icon(String fileType) {
|
||||||
|
try {
|
||||||
|
// 根据文件后缀取得桶
|
||||||
|
String storageBucket = StorageBucketEnums.getBucketByFileSuffix(fileType, "");
|
||||||
|
|
||||||
|
ClassPathResource cpr = new ClassPathResource(storageBucket + ".png");
|
||||||
|
|
||||||
|
byte[] bytes = FileCopyUtils.copyToByteArray(cpr.getInputStream());
|
||||||
|
|
||||||
|
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||||
|
attr.getResponse().setHeader("content-disposition", "inline");
|
||||||
|
attr.getResponse().setHeader("Content-Length", String.valueOf(bytes.length));
|
||||||
|
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) {
|
||||||
|
IoUtil.copy(inputStream, attr.getResponse().getOutputStream());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(MinioPlusErrorCode.FILE_ICON_FAILED.getMessage(), e);
|
||||||
|
// 图标获取失败
|
||||||
|
throw new MinioPlusException(MinioPlusErrorCode.FILE_ICON_FAILED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,112 @@
|
|||||||
|
package com.luban.api.s3.ctrl;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.liuxp.minioplus.api.model.vo.FileCheckResultVo;
|
||||||
|
import org.liuxp.minioplus.api.model.vo.FilePreShardingVo;
|
||||||
|
import org.liuxp.minioplus.extension.context.Response;
|
||||||
|
import org.liuxp.minioplus.extension.dto.FileCheckDTO;
|
||||||
|
import org.liuxp.minioplus.extension.dto.FileCompleteDTO;
|
||||||
|
import org.liuxp.minioplus.extension.dto.PreShardingDTO;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对象存储标准接口定义
|
||||||
|
* 本类的方法是给前端使用的方法
|
||||||
|
*
|
||||||
|
* @author contact@liuxp.me
|
||||||
|
* @since 2024/6/18
|
||||||
|
*/
|
||||||
|
@Tag(name = "MinIO Plus 接口")
|
||||||
|
public interface StorageWebAPI {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求地址前缀
|
||||||
|
*/
|
||||||
|
String ROOT_PATH = "/storage";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图标请求地址
|
||||||
|
*/
|
||||||
|
String ICON_PATH = "/storage/icon/";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件预分片方法
|
||||||
|
* 在大文件上传时,为了防止前端重复计算文件MD5值,提供该方法
|
||||||
|
*
|
||||||
|
* @param preShardingDTO 文件预分片入参DTO
|
||||||
|
* @return 预分片结果
|
||||||
|
*/
|
||||||
|
@Operation(summary = "文件预分片")
|
||||||
|
@PostMapping("/upload/sharding")
|
||||||
|
@ResponseBody
|
||||||
|
Response<FilePreShardingVo> sharding(@RequestBody @Validated PreShardingDTO preShardingDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传任务初始化
|
||||||
|
* 上传前的预检查:秒传、分块上传和断点续传等特性均基于该方法实现
|
||||||
|
*
|
||||||
|
* @param fileCheckDTO 文件预检查入参
|
||||||
|
* @return 检查结果
|
||||||
|
*/
|
||||||
|
@Operation(summary = "上传任务初始化")
|
||||||
|
@PostMapping("/upload/init")
|
||||||
|
@ResponseBody
|
||||||
|
Response<FileCheckResultVo> init(@RequestBody @Validated FileCheckDTO fileCheckDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件上传完成
|
||||||
|
*
|
||||||
|
* @param fileKey 文件KEY
|
||||||
|
* @param fileCompleteDTO 文件完成入参DTO
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
@Operation(summary = "上传完成")
|
||||||
|
@PostMapping("/upload/complete/{fileKey}")
|
||||||
|
@ResponseBody
|
||||||
|
Response<Object> complete(@PathVariable("fileKey") String fileKey, @RequestBody FileCompleteDTO fileCompleteDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件下载
|
||||||
|
*
|
||||||
|
* @param fileKey 文件KEY
|
||||||
|
* @return 文件下载地址
|
||||||
|
*/
|
||||||
|
@Operation(summary = "文件下载")
|
||||||
|
@GetMapping("/download/{fileKey}")
|
||||||
|
ResponseEntity<Void> download(@PathVariable("fileKey") String fileKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取图像
|
||||||
|
*
|
||||||
|
* @param fileKey 文件KEY
|
||||||
|
* @return 原图地址
|
||||||
|
*/
|
||||||
|
@Operation(summary = "图片预览 - 原图")
|
||||||
|
@GetMapping("/image/{fileKey}")
|
||||||
|
ResponseEntity<Void> previewOriginal(@PathVariable("fileKey") String fileKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件预览
|
||||||
|
* 当文件为图片时,返回图片的缩略图
|
||||||
|
* 当文件不是图片时,返回文件类型图标
|
||||||
|
*
|
||||||
|
* @param fileKey 文件KEY
|
||||||
|
* @return 缩略图地址
|
||||||
|
*/
|
||||||
|
@Operation(summary = "图片预览 - 缩略图")
|
||||||
|
@GetMapping("/preview/{fileKey}")
|
||||||
|
ResponseEntity<Void> previewMedium(@PathVariable("fileKey") String fileKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据文件类型取得图标
|
||||||
|
*
|
||||||
|
* @param fileType 文件扩展名
|
||||||
|
*/
|
||||||
|
@Operation(summary = "获取图标")
|
||||||
|
@GetMapping("/icon/{fileType}")
|
||||||
|
void icon(@PathVariable("fileType") String fileType);
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user