通过Feign跨服务上传文件,getParts错误,头信息设置,boundary为null,multipart错误等

前提

由于本人喜欢使用feign做请求转发,故而时常会遇到一些奇奇怪怪的问题
在这里声明一下,feign不是万能的,确实有一些请求不能无缝转发

基础的使用可以参考我之前的文章,可以解决因为版本升级导致无法使用等问题
https://blog.csdn.net/yuexiahunone/article/details/132175038

可以解决的问题

  • Content type ‘’ not supported
  • Failed to parse multipart servlet request
  • Current request is not a multipart request
  • feign.codec.EncodeException: Error converting request body
  • file=org.springframework.web.multipart.support.StandardMultipartHttpServletRequest%24StandardMultipartFile%402bab8d83
  • 读取流失败
  • 转换流失败

本人遇到的问题

可以略过

在服务端B读取流信息转换失败
这里报的错 Request.parseParts()
流程大概就是处理表单
获取参数 StandardMultipartHttpServletRequest.getParameterMap
表单参数不是空,初始化并转换表单信息 StandardMultipartHttpServletRequest.initializeMultipart()/parseRequest(HttpServletRequest request)
发现是文件处理文件 Request.parseParts(2562行)
初始化文件(FileItemIteratorImpl.init)
获取流长度
读取流信息
获取编码格式
获取content-type
获取boundary值 FileUploadBase.getBoundary(我这里报错了)
把流信息读取到文件中

需要断点的文件
	StandardMultipartHttpServletRequest
	HttpServletRequestWrapper
	Request
	FileUploadBase
	FileUpload
	FileItemIteratorImpl
	MultipartStream

开发环境

  • 前端为vue,使用axios插件,表单方式提交
  • 后台为springboot
  • 局域网(这个没影响)
  • 上传的是excel文件

注意事项

  • 后台feign接口参数一定要对应上
  • 头信息要设置对
  • 高版本的spring一定要修改代码,参考链接

代码排查

  • 主要是排查后台代码
  • 服务端A,feign的接参,可以使用@RequestPart和@RequestParam,我使用的是@RequestPart
  • 服务端A,feign的content-type是否设置正确,consumes = “multipart/form-data”
  • 服务端B,接口的参数要和服务端A的feign接口一致,但是不需要设置content-type
  • 服务端B在拦截器中要判断一下content-type,如果是multipart/form-data,则略过,不要在拦截器中读取流信息
  • 服务端A,不要在feign的拦截器中设置content-type,会覆盖接口上的content-type,
    例如template.header(“Content-Type”, “multipart/form-data”);,此举会导致服务端B无法读取content-lenght以及boundary值(我就是栽倒在这里了)

上代码

以下代码为伪代码
//前端
//post方式,使用data作为数据载体
export function apiUploadFile(data) {
  return request({
    url: '/backend/oak/cardInfo/uploadCardInfo',
    method: 'post',
    data: data
  })
}

function uploadFile(file){
	//这里使用表单方式提交
	let forms = new FormData()
    forms.append('file', file)
    this.apiUploadFile(forms).then(res => {
		///......
    });
}
//服务端A
@RestController
@RequestMapping(value = "/api")
@FeignClient(name = "UploadFileProvider", url = "${apiUrl}", path = "/api", configuration = {FeignUploadFileInterceptor.class})
public interface UploadFileApi {

	//consumes就是content-type,因为是文件(流信息)所以设置为multipart/form-data
	//然后feign会自动设置content-length以及boundary值,这里的boundary值会被修改
    @Operation(summary = "上传文件")
    @PostMapping(value = "/uploadFile", consumes = "multipart/form-data")
    FeignResult<Object> uploadCardInfo(@RequestPart("file") MultipartFile file);

}
//服务端B
@RestController
@RequestMapping(value = "/api")
@RequiredArgsConstructor
public class UploadFileController {

    private final OssService ossService;

    @Operation(summary = "上传卡信息")
    @PostMapping("/uploadFile")
    public Result<Void> uploadFile(@RequestPart("file") MultipartFile file) {
        return Result.data(() -> ossService.uploadFile(file));
    }

}

//拦截器代码 .....
//这里不写了,没啥东西,记住不要在这里设置content-type
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值