package com.iailab.module.infra.controller.admin.file; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.URLUtil; import com.iailab.framework.common.pojo.CommonResult; import com.iailab.framework.common.pojo.PageResult; import com.iailab.framework.common.util.object.BeanUtils; import com.iailab.module.infra.controller.admin.file.vo.file.*; import com.iailab.module.infra.dal.dataobject.file.FileDO; import com.iailab.module.infra.service.file.FileService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import javax.annotation.Resource; import javax.annotation.security.PermitAll; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import static com.iailab.framework.common.pojo.CommonResult.success; import static com.iailab.module.infra.framework.file.core.utils.FileTypeUtils.writeAttachment; @Tag(name = "管理后台 - 文件存储") @RestController @RequestMapping("/infra/file") @Validated @Slf4j public class FileController { @Resource private FileService fileService; @PostMapping("/upload") @Operation(summary = "上传文件", description = "模式一:后端上传文件") public CommonResult uploadFile(FileUploadReqVO uploadReqVO) throws Exception { MultipartFile file = uploadReqVO.getFile(); String path = uploadReqVO.getPath(); return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream()))); } @GetMapping("/presigned-url") @Operation(summary = "获取文件预签名地址", description = "模式二:前端上传文件:用于前端直接上传七牛、阿里云 OSS 等文件存储器") public CommonResult getFilePresignedUrl(@RequestParam("path") String path) throws Exception { return success(fileService.getFilePresignedUrl(path)); } @PostMapping("/create") @Operation(summary = "创建文件", description = "模式二:前端上传文件:配合 presigned-url 接口,记录上传了上传的文件") public CommonResult createFile(@Valid @RequestBody FileCreateReqVO createReqVO) { return success(fileService.createFile(createReqVO)); } @DeleteMapping("/delete") @Operation(summary = "删除文件") @Parameter(name = "id", description = "编号", required = true) @PreAuthorize("@ss.hasPermission('infra:file:delete')") public CommonResult deleteFile(@RequestParam("id") Long id) throws Exception { fileService.deleteFile(id); return success(true); } @GetMapping("/{configId}/get/**") @PermitAll @Operation(summary = "下载文件") @Parameter(name = "configId", description = "配置编号", required = true) public void getFileContent(HttpServletRequest request, HttpServletResponse response, @PathVariable("configId") Long configId) throws Exception { // 获取请求的路径 String path = StrUtil.subAfter(request.getRequestURI(), "/get/", false); if (StrUtil.isEmpty(path)) { throw new IllegalArgumentException("结尾的 path 路径必须传递"); } // 解码,解决中文路径的问题 https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/807/ path = URLUtil.decode(path); // 读取内容 byte[] content = fileService.getFileContent(configId, path); if (content == null) { log.warn("[getFileContent][configId({}) path({}) 文件不存在]", configId, path); response.setStatus(HttpStatus.NOT_FOUND.value()); return; } writeAttachment(response, path, content); } @GetMapping("/page") @Operation(summary = "获得文件分页") @PreAuthorize("@ss.hasPermission('infra:file:query')") public CommonResult> getFilePage(@Valid FilePageReqVO pageVO) { PageResult pageResult = fileService.getFilePage(pageVO); return success(BeanUtils.toBean(pageResult, FileRespVO.class)); } }