You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot项目文件操作接口仅POST可用,GET/DELETE报500错误

问题分析与修复方案

核心问题1:Optional 直接调用 get() 引发空指针异常

StorageService 的 outputFile 方法中,当 repository.findByName(fileName) 查询不到目标文件时,dbFileData 是空的 Optional 对象,直接调用 dbFileData.get() 会抛出 NoSuchElementException,这是 GET 接口返回500错误的直接原因。

修复代码:

修改 StorageService 的 outputFile 方法,先判断文件是否存在:

public byte[] outputFile(String fileName){
    Optional<FileData> dbFileData = repository.findByName(fileName);
    if(!dbFileData.isPresent()){
        throw new RuntimeException("文件不存在:" + fileName);
    }
    return decompressFile(dbFileData.get().getFileData());
}

同时在 Controller 层捕获异常,返回友好响应:

@GetMapping("/{fileName}")
public ResponseEntity<?> outputFile(@PathVariable String fileName){
    try {
        byte[] fileData = service.outputFile(fileName);
        String contentType = service.getType(fileName);
        return ResponseEntity.status(HttpStatus.OK)
                .contentType(MediaType.parseMediaType(contentType))
                .body(fileData);
    } catch (RuntimeException e) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND)
                .body(e.getMessage());
    }
}

核心问题2:GET 接口 Content-Type 设置错误

当前 GET 接口使用 MediaType.MULTIPART_FORM_DATA,这是上传文件的请求格式,返回文件内容时应该使用文件对应的实际媒体类型(如图片用 image/png、文档用 application/pdf),否则客户端无法正确解析文件。

修复代码:

从数据库中读取文件的原始类型,设置正确的 Content-Type:

@GetMapping("/{fileName}")
public ResponseEntity<?> outputFile(@PathVariable String fileName){
    try {
        Optional<FileData> dbFileData = repository.findByName(fileName);
        if(!dbFileData.isPresent()){
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                    .body("文件不存在:" + fileName);
        }
        FileData fileData = dbFileData.get();
        byte[] content = service.decompressFile(fileData.getFileData());
        return ResponseEntity.status(HttpStatus.OK)
                .contentType(MediaType.parseMediaType(fileData.getType()))
                .body(content);
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body("获取文件失败:" + e.getMessage());
    }
}

潜在问题:JPA 实体类缺少无参构造函数

FileData 实体类仅提供带参数的构造函数,而 JPA 在实例化实体时必须依赖无参构造函数。虽然当前 POST 接口正常,但会导致后续查询或持久化操作出现隐性异常。

修复代码:

给 FileData 添加无参构造函数:

@Entity
@Table(name="FileData")
@Data
public class FileData {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String type;
    @Lob
    @Column(name="filedata")
    private byte[] fileData;

    // 添加JPA必需的无参构造函数
    public FileData() {}

    public FileData(String name, String type, byte[] fileData) {
        this.name = name;
        this.type = type;
        this.fileData = fileData;
    }
}

额外优化:添加日志与异常细化

在 StorageService 中添加日志记录,方便排查问题:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Service
public class StorageService {
    private static final Logger logger = LoggerFactory.getLogger(StorageService.class);
    @Autowired
    private StorageRepository repository;

    public byte[] outputFile(String fileName){
        Optional<FileData> dbFileData = repository.findByName(fileName);
        if(!dbFileData.isPresent()){
            logger.error("未找到文件:{}", fileName);
            throw new RuntimeException("文件不存在:" + fileName);
        }
        try {
            return decompressFile(dbFileData.get().getFileData());
        } catch (Exception e) {
            logger.error("解压文件失败:{}", fileName, e);
            throw new RuntimeException("解压文件失败:" + e.getMessage());
        }
    }
}

内容的提问来源于stack exchange,提问作者Micu Bogdan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 13:35:24