xingyu 2 سال پیش
والد
کامیت
459640a222

+ 92 - 0
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java

@@ -0,0 +1,92 @@
+package cn.iocoder.yudao.module.infra.controller.admin.file;
+
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
+import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
+import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO;
+import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileRespVO;
+import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileUploadReqVO;
+import cn.iocoder.yudao.module.infra.convert.file.FileConvert;
+import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
+import cn.iocoder.yudao.module.infra.service.file.FileService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+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 javax.annotation.Resource;
+import javax.annotation.security.PermitAll;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Api(tags = "管理后台 - 文件存储")
+@RestController
+@RequestMapping("/infra/file")
+@Validated
+@Slf4j
+public class FileController {
+
+    @Resource
+    private FileService fileService;
+
+    @PostMapping("/upload")
+    @ApiOperation("上传文件")
+    @OperateLog(logArgs = false) // 上传文件,没有记录操作日志的必要
+    public CommonResult<String> uploadFile(FileUploadReqVO uploadReqVO) throws Exception {
+        MultipartFile file = uploadReqVO.getFile();
+        String path = uploadReqVO.getPath();
+        return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream())));
+    }
+
+    @DeleteMapping("/delete")
+    @ApiOperation("删除文件")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
+    @PreAuthorize("@ss.hasPermission('infra:file:delete')")
+    public CommonResult<Boolean> deleteFile(@RequestParam("id") Long id) throws Exception {
+        fileService.deleteFile(id);
+        return success(true);
+    }
+
+    @GetMapping("/{configId}/get/**")
+    @PermitAll
+    @ApiOperation("下载文件")
+    @ApiImplicitParam(name = "configId", value = "配置编号",  required = true, dataTypeClass = Long.class)
+    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 路径必须传递");
+        }
+
+        // 读取内容
+        byte[] content = fileService.getFileContent(configId, path);
+        if (content == null) {
+            log.warn("[getFileContent][configId({}) path({}) 文件不存在]", configId, path);
+            response.setStatus(HttpStatus.NOT_FOUND.value());
+            return;
+        }
+        ServletUtils.writeAttachment(response, path, content);
+    }
+
+    @GetMapping("/page")
+    @ApiOperation("获得文件分页")
+    @PreAuthorize("@ss.hasPermission('infra:file:query')")
+    public CommonResult<PageResult<FileRespVO>> getFilePage(@Valid FilePageReqVO pageVO) {
+        PageResult<FileDO> pageResult = fileService.getFilePage(pageVO);
+        return success(FileConvert.INSTANCE.convertPage(pageResult));
+    }
+
+}

+ 98 - 0
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java

@@ -0,0 +1,98 @@
+package cn.iocoder.yudao.module.infra.service.file;
+
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.io.FileUtils;
+import cn.iocoder.yudao.framework.file.core.client.FileClient;
+import cn.iocoder.yudao.framework.file.core.utils.FileTypeUtils;
+import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO;
+import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
+import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper;
+import lombok.SneakyThrows;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_NOT_EXISTS;
+
+/**
+ * 文件 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+public class FileServiceImpl implements FileService {
+
+    @Resource
+    private FileConfigService fileConfigService;
+
+    @Resource
+    private FileMapper fileMapper;
+
+    @Override
+    public PageResult<FileDO> getFilePage(FilePageReqVO pageReqVO) {
+        return fileMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    @SneakyThrows
+    public String createFile(String name, String path, byte[] content) {
+        // 计算默认的 path 名
+        String type = FileTypeUtils.getMineType(content, name);
+        if (StrUtil.isEmpty(path)) {
+            path = FileUtils.generatePath(content, name);
+        }
+        // 如果 name 为空,则使用 path 填充
+        if (StrUtil.isEmpty(name)) {
+            name = path;
+        }
+
+        // 上传到文件存储器
+        FileClient client = fileConfigService.getMasterFileClient();
+        Assert.notNull(client, "客户端(master) 不能为空");
+        String url = client.upload(content, path, type);
+
+        // 保存到数据库
+        FileDO file = new FileDO();
+        file.setConfigId(client.getId());
+        file.setName(name);
+        file.setPath(path);
+        file.setUrl(url);
+        file.setType(type);
+        file.setSize(content.length);
+        fileMapper.insert(file);
+        return url;
+    }
+
+    @Override
+    public void deleteFile(Long id) throws Exception {
+        // 校验存在
+        FileDO file = this.validateFileExists(id);
+
+        // 从文件存储器中删除
+        FileClient client = fileConfigService.getFileClient(file.getConfigId());
+        Assert.notNull(client, "客户端({}) 不能为空", file.getConfigId());
+        client.delete(file.getPath());
+
+        // 删除记录
+        fileMapper.deleteById(id);
+    }
+
+    private FileDO validateFileExists(Long id) {
+        FileDO fileDO = fileMapper.selectById(id);
+        if (fileDO == null) {
+            throw exception(FILE_NOT_EXISTS);
+        }
+        return fileDO;
+    }
+
+    @Override
+    public byte[] getFileContent(Long configId, String path) throws Exception {
+        FileClient client = fileConfigService.getFileClient(configId);
+        Assert.notNull(client, "客户端({}) 不能为空", configId);
+        return client.getContent(path);
+    }
+
+}