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

Spring Boot传递MultipartFile至服务器的序列化问题求助

问题:Spring Boot文件上传客户端序列化失败

在Spring Boot项目中,尝试通过服务器将文件存入数据库,选择用MultipartFile传递文件,但遇到序列化错误:

Caused by: jakarta.ws.rs.client.ResponseProcessingException: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.mock.web.MockMultipartFile["inputStream"])
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.mock.web.MockMultipartFile["inputStream"])

已在application.properties中添加spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false,但问题依旧。Gradle构建已成功,Postman测试上传功能正常,但客户端代码调用失败。

相关代码如下:

客户端ServerUtils代码

public void saveFile(File file) throws IOException {
        internalPostRequest("secure/" + store.accessStore().getUsername() + "/file/add",
                Entity.entity(convert(file), APPLICATION_JSON), new GenericType<>(){});
    }
public static MultipartFile convert(File file) throws IOException {
        String filename = file.getName();
        FileInputStream inputStream = new FileInputStream(file);
        return new MockMultipartFile(filename, inputStream);
    }
private <T> T internalPostRequest(String path, Entity send, GenericType<T> retType) {
        return ClientBuilder.newClient(new ClientConfig())
                .target(getServer()).path(path)
                .request(APPLICATION_JSON)
                .accept(APPLICATION_JSON)
                .post(send, retType);
    }

服务端FileController代码

public class FileController {
    @Autowired
    private StorageService service;
    @PostMapping("/add")
    public ResponseEntity<?> uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
        String uploadFile = service.uploadFile(file);
        return ResponseEntity.status(HttpStatus.OK)
                .body(uploadFile);
    }
}

服务端StorageService代码

@Service
public class StorageService {
    @Autowired
    private StorageRepository repository;

    public String uploadFile(MultipartFile file) throws IOException {
        repository.save(new FileData(file.getOriginalFilename(),
                file.getContentType(), compressFile(file.getBytes())));
        return "File uploaded succesfully: "+ file.getOriginalFilename();
    }
    public String getType(String fileName){
        Optional<FileData> dbFileData = repository.findByName(fileName);
        if (dbFileData.isPresent()) {
            return dbFileData.get().getType();
        } else {
            return "File not found: " + fileName;
        }
    }
    public static byte[] compressFile(byte[] data) {
        Deflater deflater = new Deflater();
        deflater.setLevel(Deflater.BEST_COMPRESSION);
        deflater.setInput(data);
        deflater.finish();

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
        byte[] tmp = new byte[4*1024];
        while (!deflater.finished()) {
            int size = deflater.deflate(tmp);
            outputStream.write(tmp, 0, size);
        }
        try {
            outputStream.close();
        } catch (Exception ignored) {
        }
        return outputStream.toByteArray();
    }
}

解决方案

核心问题分析

客户端错误地将MultipartFile以APPLICATION_JSON格式发送,Jackson尝试序列化MockMultipartFile内部的ByteArrayInputStream,而该类没有可序列化的属性,导致报错。Postman正常是因为它用的是multipart/form-data格式,符合服务端@RequestParam("file")的接收要求。

修复步骤

  1. 客户端改用multipart/form-data格式发送请求
    不要直接序列化MultipartFile,而是构建multipart表单数据。修改客户端saveFile和internalPostRequest方法:

    public void saveFile(File file) throws IOException {
        // 构建multipart表单
        FormDataMultiPart formData = new FormDataMultiPart();
        // 将文件转为InputStream,添加到表单中
        try (FileInputStream fis = new FileInputStream(file)) {
            formData.field("file", fis, MediaType.MULTIPART_FORM_DATA_TYPE, file.getName());
            internalPostRequest("secure/" + store.accessStore().getUsername() + "/file/add",
                    Entity.entity(formData, MediaType.MULTIPART_FORM_DATA_TYPE), new GenericType<>(){});
        }
    }
    
    private <T> T internalPostRequest(String path, Entity send, GenericType<T> retType) {
        return ClientBuilder.newClient(new ClientConfig())
                .target(getServer()).path(path)
                .request(MediaType.APPLICATION_JSON) // 接收JSON响应
                .post(send, retType);
    }
    
  2. 移除无效配置(可选)
    之前添加的spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false对这个问题无效,可以从application.properties中删除,因为问题根源不是空Bean序列化,而是错误的请求格式。

  3. 优化文件转换逻辑(可选)
    客户端不需要创建MockMultipartFile对象,直接用文件流构建multipart表单即可,可移除原有的convert方法。

验证

修改后重新调用客户端的saveFile方法,即可正常上传文件,不会再出现序列化错误。

内容的提问来源于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.26 04:10:45