1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package com.se.simu.controller;
 
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
 
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.zip.ZipEntry;
 
@Api(tags = "0-文件相关接口")
@Slf4j
@CrossOrigin(origins = "*")
@RestController
@RequestMapping("/v1/files")
public class FilesUploadController {
 
 
    @Value("${simu-app.filePath}")
    //  private final String uploadedFolder = "D:/home/scheme/upload";
    private String uploadedFolder;
 
 
    @ApiOperation("0-文件上传地址")
    @GetMapping("/getUploadPath")
    public ResponseEntity<String> getUploadPath() throws Exception {
        return ResponseEntity.ok("文件上传地址为:" + uploadedFolder);
    }
 
 
    @ApiOperation("1-上传单个文件")
    @ApiImplicitParam(name = "filePathName", value = "文件夹名称", required = true, dataType = "String", paramType = "query", example = "upload", dataTypeClass = String.class)
    @PostMapping("/uploadSingleFile")
    public ResponseEntity<String> uploadSingleFile(@RequestParam("file") MultipartFile file, @RequestParam("filePathName") String filePathName) throws IOException {
        if (file.isEmpty()) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("文件不能为空");
        }
        // 判断 filePathName 是否为空
        if (filePathName == null || filePathName.isEmpty()) {
            filePathName = "upload";
            //return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("文件夹名称不能为空");
        }
        String targetDir = Paths.get(uploadedFolder, filePathName).toString();
        log.info("目标目录: {}", targetDir);
        createDirectoriesIfNotExists(targetDir);
        try {
            file.transferTo(Paths.get(targetDir, file.getOriginalFilename()));
            return ResponseEntity.ok("文件上传成功");
        } catch (IOException e) {
            log.error("文件上传失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件上传失败");
        }
    }
 
    @ApiOperation("2-上传多个文件")
    @ApiImplicitParam(name = "filePathName", value = "文件夹名称", required = true, dataType = "String", paramType = "query", example = "upload", dataTypeClass = String.class)
    @PostMapping("/uploadMultipleFiles")
    public ResponseEntity<String> uploadMultipleFiles(List<MultipartFile> files, @RequestParam("filePathName") String filePathName) throws IOException {
        // 判断 filePathName 是否为空
        if (filePathName == null || filePathName.isEmpty()) {
            //  return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("文件夹名称不能为空");
            filePathName = "upload";
        }
        // 上传文件路径
        String targetDir = Paths.get(uploadedFolder, filePathName).toString();
        log.info("目标目录: {}", targetDir);
        createDirectoriesIfNotExists(targetDir);
        CompletableFuture<Void> allUploadTasks = CompletableFuture.allOf(files.stream()
                .map(file -> CompletableFuture.runAsync(() -> {
                    try {
                        file.transferTo(Paths.get(targetDir, file.getOriginalFilename()));
                    } catch (IOException e) {
                        log.error("文件上传失败", e);
                        throw new RuntimeException("文件上传失败");
                    }
                })).toArray(CompletableFuture[]::new));
        try {
            allUploadTasks.get();
            return ResponseEntity.ok("所有文件上传成功!上传目录为:" + targetDir);
        } catch (InterruptedException | ExecutionException e) {
            log.error("文件上传失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件上传失败");
        }
    }
 
 
    @ApiOperation("2-1上传多个文件")
    @ApiImplicitParam(name = "filePathName", value = "文件夹名称", required = true, dataType = "String", paramType = "query", example = "upload", dataTypeClass = String.class)
    @PostMapping("/uploadMultipleFile")
    public ResponseEntity<String> uploadMultipleFile(List<MultipartFile> files, @RequestParam("filePathName") String filePathName) throws IOException {
        // 上传文件路径
        String targetDir = Paths.get(uploadedFolder, filePathName).toString();
        log.info("目标目录: {}", targetDir);
        createDirectoriesIfNotExists(targetDir);
        try {
            for (MultipartFile file : files) {
                String fileName = file.getOriginalFilename();
                File targetFile = new File(targetDir, fileName);
                file.transferTo(targetFile);
            }
            return ResponseEntity.ok("所有文件上传成功!上传目录为:" + targetDir);
        } catch (IOException e) {
            log.error("文件上传失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件上传失败");
        }
    }
 
 
    private File newFile(File destinationDir, ZipEntry zipEntry) throws Exception {
        File destFile = new File(destinationDir, zipEntry.getName());
 
        String destDirPath = destinationDir.getCanonicalPath();
        String destFilePath = destFile.getCanonicalPath();
 
        if (!destFilePath.startsWith(destDirPath + File.separator)) {
            throw new Exception("Entry is outside of the target dir: " + zipEntry.getName());
        }
 
        return destFile;
    }
 
 
    /**
     * 按文件路径删除文件夹
     * 递归删除文件夹及文件的方法
     *
     * @param folder 文件夹
     */
    private void deleteFolderByFilePath(File folder) {
        if (folder.exists()) {
            File[] files = folder.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        // 递归删除子文件夹
                        deleteFolderByFilePath(file);
                    } else {
                        // 删除文件
                        file.delete();
                    }
                }
            }
            // 删除文件夹本身
            folder.delete();
        }
    }
 
 
    /**
     * @param targetDir 目标目录
     * @throws IOException
     */
    private void createDirectoriesIfNotExists(String targetDir) throws IOException {
        Path path = Paths.get(targetDir);
        if (!Files.exists(path)) {
            Files.createDirectories(path);
        }
    }
 
    private Boolean directoriesIfNotExists(String targetDir) throws IOException {
        Path path = Paths.get(targetDir);
        if (!Files.exists(path)) {
            // Files.createDirectories(path);
            return false;
        } else {
            return true;
        }
    }
 
 
}