From 1362b37c591fa9b21e718f339f776ee8ce00349a Mon Sep 17 00:00:00 2001 From: zhaodengke Date: Fri, 10 Nov 2023 14:41:45 +0800 Subject: [PATCH] upload --- .../controller/file/FileSystemController.java | 19 ++ .../controller/open/OpenFileController.java | 2 +- .../ruoyi/common/utils/file/PathUtils.java | 2 +- .../java/com/ruoyi/file/model/FileModel.java | 14 +- .../com/ruoyi/file/request/PutFileReq.java | 23 ++ .../ruoyi/file/service/FileSystemService.java | 61 ++++++ ruoyi-ui/src/components/ServerFileChooser.vue | 11 + ruoyi-ui/src/views/file/fs/index.vue | 204 ++++++++++++++++++ 8 files changed, 333 insertions(+), 3 deletions(-) create mode 100644 ruoyi-file/src/main/java/com/ruoyi/file/request/PutFileReq.java create mode 100644 ruoyi-ui/src/views/file/fs/index.vue diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/file/FileSystemController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/file/FileSystemController.java index c3f9b7e..82b4dac 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/file/FileSystemController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/file/FileSystemController.java @@ -4,15 +4,22 @@ import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.file.model.FileModel; import com.ruoyi.file.model.FileSystemFilter; +import com.ruoyi.file.object.UploadResp; +import com.ruoyi.file.request.PutFileReq; import com.ruoyi.file.service.FileSystemService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import javax.validation.Valid; import java.util.List; /** @@ -42,4 +49,16 @@ public class FileSystemController extends BaseController return AjaxResult.success(list); } + /** + * 上传文件 + */ + @ApiOperation("上传文件") + @PreAuthorize("@ss.hasPermi('admin:fs:put')") + @PostMapping("/put") + public AjaxResult put(@Valid PutFileReq req, MultipartFile file) + { + FileModel upload = fileSystemService.put(req, file); + return AjaxResult.success(upload); + } + } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/open/OpenFileController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/open/OpenFileController.java index 22c08de..aef1fbf 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/open/OpenFileController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/open/OpenFileController.java @@ -48,7 +48,7 @@ public class OpenFileController * @param fileName 文件名称 * @param delete 是否删除 */ - @GetMapping("/download") + //@GetMapping("/download") public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) { try diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/PathUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/PathUtils.java index 7272941..e392622 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/PathUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/PathUtils.java @@ -95,7 +95,7 @@ public final class PathUtils else if(i == part.length() - 1) return part; else - return part.substring(0, i); + return part.substring(0, i + 1); } private PathUtils() {} diff --git a/ruoyi-file/src/main/java/com/ruoyi/file/model/FileModel.java b/ruoyi-file/src/main/java/com/ruoyi/file/model/FileModel.java index 717d213..90dc91a 100644 --- a/ruoyi-file/src/main/java/com/ruoyi/file/model/FileModel.java +++ b/ruoyi-file/src/main/java/com/ruoyi/file/model/FileModel.java @@ -6,10 +6,12 @@ import com.ruoyi.file.enums.FileType; import lombok.Data; import java.io.File; +import java.util.Comparator; import java.util.List; +import java.util.Objects; @Data -public final class FileModel +public final class FileModel implements Comparator { private String fileName; private String filePath; @@ -42,4 +44,14 @@ public final class FileModel filePath = PathUtils.normalizeSlash(filePath); type = FileType.FileType(file); } + + @Override + public int compare(Object o1, Object o2) + { + FileModel a = (FileModel)o1; + FileModel b = (FileModel)o2; + if(Objects.equals(a.type, b.type)) + return a.fileName.compareToIgnoreCase(b.fileName); + return -(a.type - b.type); + } } diff --git a/ruoyi-file/src/main/java/com/ruoyi/file/request/PutFileReq.java b/ruoyi-file/src/main/java/com/ruoyi/file/request/PutFileReq.java new file mode 100644 index 0000000..3d8034f --- /dev/null +++ b/ruoyi-file/src/main/java/com/ruoyi/file/request/PutFileReq.java @@ -0,0 +1,23 @@ +package com.ruoyi.file.request; + +import lombok.Data; + +import javax.validation.constraints.NotEmpty; + +@Data +public final class PutFileReq +{ + @NotEmpty(message = "上传路径不能为空") + private String path; + private Integer ifExists; + + public boolean allowOverride() + { + return null != ifExists && ifExists == 2; + } + + public boolean allowRename() + { + return null != ifExists && ifExists == 1; + } +} diff --git a/ruoyi-file/src/main/java/com/ruoyi/file/service/FileSystemService.java b/ruoyi-file/src/main/java/com/ruoyi/file/service/FileSystemService.java index 0a8f2ac..6c45f82 100644 --- a/ruoyi-file/src/main/java/com/ruoyi/file/service/FileSystemService.java +++ b/ruoyi-file/src/main/java/com/ruoyi/file/service/FileSystemService.java @@ -1,13 +1,19 @@ package com.ruoyi.file.service; +import cn.hutool.core.io.FileUtil; import com.ruoyi.common.exception.ASSERT; import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.file.PathUtils; import com.ruoyi.file.model.FileSystemFilter; import com.ruoyi.file.model.FileModel; +import com.ruoyi.file.request.PutFileReq; +import org.apache.commons.io.FilenameUtils; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; @Service @@ -36,6 +42,61 @@ public class FileSystemService list.add(new FileModel(f)); } } + list.sort(new FileModel()); return list; } + + public FileModel put(PutFileReq req, MultipartFile file) + { + String dst = PathUtils.appendPaths(req.getPath(), file.getOriginalFilename()); + File dstFile = new File(dst); + if(dstFile.exists()) + { + if(dstFile.isDirectory()) + throw new RuntimeException("目标文件是目录: " + dst); + if(req.allowRename()) + { + int i = 1; + do + { + String originalFilename = file.getOriginalFilename(); + String extension = FilenameUtils.getExtension(originalFilename); + originalFilename = PathUtils.removeExtension(originalFilename); + originalFilename += "(" + i++ + ")"; + if(StringUtils.isNotEmpty(extension)) + originalFilename += "." + extension; + dst = PathUtils.appendPaths(req.getPath(), originalFilename); + dstFile = new File(dst); + } while(dstFile.exists()); + } + else if(req.allowOverride()) + { + // override + } + else + throw new RuntimeException("目标文件已存在: " + dst); + } + + File parentFile = dstFile.getParentFile(); + if(null == parentFile) + throw new RuntimeException("必须指定存储目录: " + dst); + if(parentFile.exists() && !parentFile.isDirectory()) + throw new RuntimeException("存储目录必须是文件夹: " + dst); + if(!parentFile.exists()) + { + if(!parentFile.mkdirs()) + throw new RuntimeException("存储目录不存在且创建失败: " + dst); + } + try + { + byte[] bytes = file.getBytes(); + FileUtil.writeBytes(bytes, dstFile); + return new FileModel(dstFile); + } + catch(Exception e) + { + e.printStackTrace(); + throw new RuntimeException(e); + } + } } diff --git a/ruoyi-ui/src/components/ServerFileChooser.vue b/ruoyi-ui/src/components/ServerFileChooser.vue index 2aa93e6..48f301a 100644 --- a/ruoyi-ui/src/components/ServerFileChooser.vue +++ b/ruoyi-ui/src/components/ServerFileChooser.vue @@ -60,6 +60,17 @@ export default { this.$emit('input', data.filePath); this.$emit('selected', data); }, + reload() { + this.files = []; + let query = { + filePath: null, + fileType: this.fileType, + showHidden: this.showHidden, + }; + ls(query).then((resp) => { + this.files = resp.data; + }); + }, } }; diff --git a/ruoyi-ui/src/views/file/fs/index.vue b/ruoyi-ui/src/views/file/fs/index.vue new file mode 100644 index 0000000..b5966c6 --- /dev/null +++ b/ruoyi-ui/src/views/file/fs/index.vue @@ -0,0 +1,204 @@ + + +