Spring Cloud中FeignClient实现文件上传功能
项目概况:SpringCloud搭的微服务,使用了eureka,FeignClient,现在遇到FeignClient调用接口时不支持上传文件,
百度到两种方案,一种是使用feign-form和feign-form-spring库来做,源码地址。
具体的使用方法是加入maven依赖
io.github.openfeign.form feign-form-spring 3.2.2 io.github.openfeign.form feign-form 3.2.2
注入SpringFormEncoder类
@Bean
@Primary
@Scope("prototype")
publicEncodermultipartFormEncoder(){
returnnewSpringFormEncoder();
}
FeignClient接口里方法参数是文件类型的要用@RequestPart注解,且要设置ContentType为multipart/form-data
@ResponseBody
@RequestMapping(value="/ctstestcase/updateTestCase",method={RequestMethod.POST},consumes=MediaType.MULTIPART_FORM_DATA_VALUE)
MapupdateTestCase(@RequestParam("testcaseId")StringtestcaseId,
@RequestParam("name")Stringname,@RequestParam("assignId")StringassignId,
@RequestParam("areaId")StringareaId,@RequestParam("state")Integerstate,
@RequestParam("iterationId")StringiterationId,@RequestParam("priority")Integerpriority,
@RequestParam("moduleId")StringmoduleId,@RequestParam("executionType")IntegerexecutionType,
@RequestParam("summary")Stringsummary,@RequestParam("tcsteps")Stringtcsteps,
@RequestParam("relations")Stringrelations,@RequestParam("attachments")Stringattachments,
@RequestPart("files")MultipartFile[]files);
但遇到一个问题,就是不支持文件数组类型,我看了源码,发现源码里底层是有对MultipartFile[]类型的支持的,源码中有个类叫SpringManyMultipartFilesWriter,是专门针对文件数组类型进行操作的,但是配置到项目里的SpringFormEncoder类里却没有对文件数组类型的判断,以致不能支持文件数组的上传.。
SpringManyMultipartFilesWriter源码:
@FieldDefaults(level=PRIVATE,makeFinal=true)
publicclassSpringManyMultipartFilesWriterextendsAbstractWriter{
SpringSingleMultipartFileWriterfileWriter=newSpringSingleMultipartFileWriter();
@Override
publicvoidwrite(Outputoutput,Stringboundary,Stringkey,Objectvalue)throwsException{
if(valueinstanceofMultipartFile[]){
valfiles=(MultipartFile[])value;
for(valfile:files){
fileWriter.write(output,boundary,key,file);
}
}elseif(valueinstanceofIterable){
valiterable=(Iterable>)value;
for(valfile:iterable){
fileWriter.write(output,boundary,key,file);
}
}
}
@Override
publicbooleanisApplicable(Objectvalue){
if(value==null){
returnfalse;
}
if(valueinstanceofMultipartFile[]){
returntrue;
}
if(valueinstanceofIterable){
valiterable=(Iterable>)value;
valiterator=iterable.iterator();
if(iterator.hasNext()&&iterator.next()instanceofMultipartFile){
returntrue;
}
}
returnfalse;
}
SpringFormEncoder源码:
publicclassSpringFormEncoderextendsFormEncoder{
/**
*ConstructorwiththedefaultFeign'sencoderasadelegate.
*/
publicSpringFormEncoder(){
this(newEncoder.Default());
}
/**
*Constructorwithspecifieddelegateencoder.
*
*@paramdelegatedelegateencoder,ifthisencodercouldn'tencodeobject.
*/
publicSpringFormEncoder(Encoderdelegate){
super(delegate);
valprocessor=(MultipartFormContentProcessor)getContentProcessor(MULTIPART);
processor.addWriter(newSpringSingleMultipartFileWriter());
processor.addWriter(newSpringManyMultipartFilesWriter());
}
@Override
publicvoidencode(Objectobject,TypebodyType,RequestTemplatetemplate)throwsEncodeException{
if(!bodyType.equals(MultipartFile.class)){
super.encode(object,bodyType,template);
return;
}
valfile=(MultipartFile)object;
valdata=singletonMap(file.getName(),object);
super.encode(data,MAP_STRING_WILDCARD,template);
}
}
从上面SpringFormEncoder的源码上可以看到SpringFormEncoder类构造时把SpringManyMultipartFilesWriter实例添加到了处理器列表里了,但是在encode方法里又只判断了MultipartFile类型,没有判断数组类型,这就比较奇怪了,底层有对数组的支持但上层却缺少了相应判断,而且在源码里的test包里也没有对文件数组类型的测试,难道只是encode方法里漏掉了?还是说那个文件数组的支持有问题?所以encode方法里才没有加入对其的判断?
于是我先试着对encode方法进行扩展加入对文件数组的判断,应该就可以支持文件数组的上传了,于是把SpringFormEncoder类源码复制出来重命名为FeignSpringFormEncoder,源码如下:
publicclassFeignSpringFormEncoderextendsFormEncoder{
/**
*ConstructorwiththedefaultFeign'sencoderasadelegate.
*/
publicFeignSpringFormEncoder(){
this(newEncoder.Default());
}
/**
*Constructorwithspecifieddelegateencoder.
*
*@paramdelegatedelegateencoder,ifthisencodercouldn'tencodeobject.
*/
publicFeignSpringFormEncoder(Encoderdelegate){
super(delegate);
valprocessor=(MultipartFormContentProcessor)getContentProcessor(MULTIPART);
processor.addWriter(newSpringSingleMultipartFileWriter());
processor.addWriter(newSpringManyMultipartFilesWriter());
}
@Override
publicvoidencode(Objectobject,TypebodyType,RequestTemplatetemplate)throwsEncodeException{
if(bodyType.equals(MultipartFile.class)){
valfile=(MultipartFile)object;
valdata=singletonMap(file.getName(),object);
super.encode(data,MAP_STRING_WILDCARD,template);
return;
}elseif(bodyType.equals(MultipartFile[].class)){
valfile=(MultipartFile[])object;
if(file!=null){
valdata=singletonMap(file.length==0?"":file[0].getName(),object);
super.encode(data,MAP_STRING_WILDCARD,template);
return;
}
}
super.encode(object,bodyType,template);
}
}
经过测试,已经可以支持文件数组了,完美解决。
这里再顺便说一下当时还百度到另一个解决文件上传的方案,这个方案就不细说了,直接上我用到的那个开源代码的地址
这个我试过也是可以解决文件上传问题的,但问题是FeignClient不能用SpringMVC的注解,得用Feign自带的注解,也因此我才扩展了第一种方法来做的文件上传功能。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。