文件上传增删改查(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处理文件的上传、存储、读取、删除和更新。可以根据需要扩展和调整此示例,以满足实际的业务需求。

posted @ 2024-07-04 19:36  gongchengship  阅读(33)  评论(0编辑  收藏  举报