Spring MultipartFile初步解析

Spring中的MultipartFile

为什么要使用MultipartFile

在进行业务开发过程中,有时会需要用户上传图片、文档、视频等文件到表单,并向后端发送Post请求。

在SpringBoot中,就需要需要通过MultipartFile用来接收前端表单中上传的文件,得益于java注解,可以非常容易的定义接收的参数为MultipartFile

public interface TestService {
  @RequestMapping("/your/url")
  RespDTO<ResponseClass> uploadFile(
    @RequestParam String authId,
    @RequestPart(required = false) MultipartFile multipartFile
  );
}

MultipartFileFile

在接收到前端表单中上传的文件后,为了在后端方便进行处理,往往会先把MultipartFile转换成File再进行后续操作。

public static File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException {
  String filename = multipartFile.getOriginalFilename();
  if (filename == null) {
    throw new IllegalStateException("MultipartFile's original name is NULL!");
  }
  Path tempFile = Files.createTempFile("", filename);
  multipartFile.transferTo(tempFile);
  return tempFile.toFile();
}

在Spring Cloud环境下Jackson序列化器报错

当在Spring Cloud跨服务传递MultipartFile时,会出现序列化错误,具体报错信息如下:

Type definition error: [simple type, class java.io.FileDescriptor]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.FileDescriptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.LinkedHashMap["imageFile"]->org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile["inputStream"]->java.io.FileInputStream["fd"])

具体含义为:在试图将包含MultipartFile对象的实体进行JSON序列化时发生的,而MultipartFile内部的inputStream关联到了FileInputStream,进一步关联到了FileDescriptor对象,这些类型在默认情况下无法被Jackson自动序列化。

解决方案一

使用Base64字符串解决

客户端接收到MultipartFile文件后通过MultipartFilegetBytes()方法转为byte[]数组,再通过Base64工具类把byte[]数组转为Base64字符串,并发送给另一个服务

另一个服务收到Base64字符串时,再用Base64工具类把字符串转为byte[]数组,之后把byte[]作为输入流,从中读取数据,写入输出流,解决报错。

解决方案二

Spring Boot中的请求注解提供了对应的属性用于规定接收的MulitipartFile类型:

public interface TestService {
  @PostMapping(value = "/your/url", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
  RespDTO<ResponseClass> uploadFile(
    @RequestParam String authId,
    @RequestPart(required = false) MultipartFile multipartFile
  );
}

consumes = MediaType.MULTIPART_FORM_DATA_VALUE:表明该方法期望接收的数据类型是multipart/form-data。这是典型的文件上传请求所使用的Content-Type,因为通过HTML表单上传文件时,浏览器会以这种方式编码数据,允许同时传输文本字段和文件内容。

produces = MediaType.APPLICATION_JSON_VALUE:声明该方法在处理请求完成后,会生成一个Content-Type为application/json的响应。这意味着方法的返回值应当是一个可以被转换为JSON格式的对象。

在这种场景下,如果你在处理文件上传后,试图直接返回包含MultipartFile或其内部不可JSON序列化组件的对象,就会触发前面讨论过的序列化错误。正确的方式应该是:

  1. 将上传的文件保存至服务器或第三方存储服务。
  2. 创建一个自定义响应对象,其中包含上传成功后需要返回给客户端的文件相关信息(如文件ID、URL、状态等)。
  3. 返回这个自定义响应对象,它会被自动转换为JSON格式并发送给客户端。

参考

multipartfile转file

SpringCloud 下 MultipartFile 序列化(JSON)出错的解决方案

  • 27
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值