文件上传增删改查(CRUD)API接口示例
为了为文件上传增删改查(CRUD)API接口并带上版本号,可以按照以下方式设计URL和实现相应的功能。我们将为上传文件、获取文件列表、获取单个文件、删除文件和更新文件内容创建API端点。
API 设计
- POST /api/v1/files/upload:上传文件
- GET /api/v1/files:获取文件列表
- GET /api/v1/files/{filename}:获取单个文件
- DELETE /api/v1/files/{filename}:删除文件
- PUT /api/v1/files/{filename}:更新文件
完整的实现
1. 创建控制器 FileController
package com.example.fileuploaddemo.controller;
import com.example.fileuploaddemo.service.FileStorageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/api/v1/files")
public class FileController {
@Autowired
private FileStorageService fileStorageService;
@PostMapping("/upload")
public ResponseEntity<Map<String, String>> uploadFile(@RequestParam("file") MultipartFile file) {
String message;
try {
String fileName = fileStorageService.save(file);
message = "Uploaded the file successfully: " + fileName;
return ResponseEntity.status(HttpStatus.OK).body(Map.of("message", message));
} catch (Exception e) {
message = "Could not upload the file: " + file.getOriginalFilename() + "!";
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(Map.of("message", message));
}
}
@GetMapping
public ResponseEntity<List<String>> listFiles() {
List<String> fileNames = fileStorageService.loadAll().map(Path::getFileName).map(Path::toString).collect(Collectors.toList());
return ResponseEntity.status(HttpStatus.OK).body(fileNames);
}
@GetMapping("/{filename}")
public ResponseEntity<Resource> getFile(@PathVariable String filename) {
Resource file = fileStorageService.loadAsResource(filename);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"")
.body(file);
}
@DeleteMapping("/{filename}")
public ResponseEntity<Map<String, String>> deleteFile(@PathVariable String filename) {
try {
fileStorageService.delete(filename);
return ResponseEntity.status(HttpStatus.OK).body(Map.of("message", "Deleted the file successfully: " + filename));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(Map.of("message", "Could not delete the file: " + filename + "!"));
}
}
@PutMapping("/{filename}")
public ResponseEntity<Map<String, String>> updateFile(@PathVariable String filename, @RequestParam("file") MultipartFile file) {
try {
fileStorageService.update(filename, file);
return ResponseEntity.status(HttpStatus.OK).body(Map.of("message", "Updated the file successfully: " + filename));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(Map.of("message", "Could not update the file: " + filename + "!"));
}
}
}
2. 更新服务 FileStorageService
package com.example.fileuploaddemo.service;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.nio.file.*;
import java.util.stream.Stream;
@Service
public class FileStorageService {
private final Path fileStorageLocation = Paths.get("uploads").toAbsolutePath().normalize();
public FileStorageService() {
try {
Files.createDirectories(this.fileStorageLocation);
} catch (Exception ex) {
throw new RuntimeException("Could not create the directory where the uploaded files will be stored.", ex);
}
}
public String save(MultipartFile file) {
try {
String fileName = file.getOriginalFilename();
Path targetLocation = this.fileStorageLocation.resolve(fileName);
Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
return fileName;
} catch (IOException ex) {
throw new RuntimeException("Could not store file " + file.getOriginalFilename() + ". Please try again!", ex);
}
}
public Stream<Path> loadAll() {
try {
return Files.walk(this.fileStorageLocation, 1).filter(path -> !path.equals(this.fileStorageLocation)).map(this.fileStorageLocation::relativize);
} catch (IOException ex) {
throw new RuntimeException("Could not read the files!", ex);
}
}
public Resource loadAsResource(String fileName) {
try {
Path filePath = this.fileStorageLocation.resolve(fileName).normalize();
Resource resource = new UrlResource(filePath.toUri());
if (resource.exists() || resource.isReadable()) {
return resource;
} else {
throw new RuntimeException("Could not read the file: " + fileName);
}
} catch (MalformedURLException ex) {
throw new RuntimeException("Could not read the file: " + fileName, ex);
}
}
public void delete(String fileName) {
try {
Path filePath = this.fileStorageLocation.resolve(fileName).normalize();
Files.deleteIfExists(filePath);
} catch (IOException ex) {
throw new RuntimeException("Could not delete the file: " + fileName, ex);
}
}
public void update(String fileName, MultipartFile file) {
try {
Path targetLocation = this.fileStorageLocation.resolve(fileName);
Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
throw new RuntimeException("Could not update the file " + file.getOriginalFilename() + ". Please try again!", ex);
}
}
}
3. 主应用程序类
package com.example.fileuploaddemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class FileUploadDemoApplication {
public static void main(String[] args) {
SpringApplication.run(FileUploadDemoApplication.class, args);
}
}
4. 配置文件
在 src/main/resources
目录下的 application.properties
文件中添加任何需要的配置(通常不需要特别配置)。
测试
启动应用程序后,可以使用工具(如Postman)进行如下测试:
- 上传文件:POST
http://localhost:8080/api/v1/files/upload
,选择文件进行上传。 - 获取文件列表:GET
http://localhost:8080/api/v1/files
。 - 获取单个文件:GET
http://localhost:8080/api/v1/files/{filename}
。 - 删除文件:DELETE
http://localhost:8080/api/v1/files/{filename}
。 - 更新文件:PUT
http://localhost:8080/api/v1/files/{filename}
,选择新的文件进行更新。
总结
通过以上步骤,我们创建了一个文件上传接口并生成了增删改查的API。这个示例展示了如何使用Spring Boot处理文件的上传、存储、读取、删除和更新。可以根据需要扩展和调整此示例,以满足实际的业务需求。