使用Feign实现微服务间文件传输
在很多时候我们会遇到微服务之间文件传输,很多时候我们可以通过序列化等方式解决(如图片等)。
最近项目中有个excel上传,以及多媒体文件上传,直接报错。
也试了2种解决方式,都不可行。
1.写一个文件Encoder解析器,会出现其他的rest请求出现encoder错误
2.springcloudfeign有一个规范,不可以传输2个对象,可以是一个对象带几个参数方式。
那么我们现在需要一种方式,不配置全局的解析器,而是通过FeignBuilder去管理上传文件,这种方式管理起来也较为方便。
引用包
com.netflix.feign feign-core 8.17.0 com.netflix.feign feign-jackson 8.17.0 com.netflix.feign feign-slf4j 8.17.0
调用方式
@ApiOperation(value="上传Excel",notes="上传Excel") @RequestMapping(value="/imExcel",method=RequestMethod.POST,produces=request_headers) publicActionResultimExcel(@RequestBodyMultipartFilefile,@RequestParam("operatorId")IntegeroperatorId){ if(file==null||file.isEmpty()||operatorId==null) returnnewActionResult<>(ResultType.BAD_REQUEST,"文件与操作用户ID都不能为空"); StringfileName=file.getOriginalFilename(); if(!fileName.matches("^.+\\.(?i)(xls)$")&&!fileName.matches("^.+\\.(?i)(xlsx)$")){ returnnewActionResult<>(ResultType.BAD_REQUEST,"上传文件格式错误,请上传后缀为.xls或.xlsx的文件"); } Feign.Builderencoder=Feign.builder() .decoder(newJacksonDecoder()) .encoder(newFeignEncoder()); FileUploadcomplainFileUpload=encoder.target(FileUpload.class,LABEL_URL); returncomplainFileUpload.imComplainExcel(file,operatorId); }
文件Encode
importfeign.RequestTemplate; importfeign.codec.EncodeException; importfeign.codec.Encoder; importorg.springframework.core.io.InputStreamResource; importorg.springframework.core.io.Resource; importorg.springframework.http.HttpEntity; importorg.springframework.http.HttpHeaders; importorg.springframework.http.HttpOutputMessage; importorg.springframework.http.MediaType; importorg.springframework.http.converter.HttpMessageConverter; importorg.springframework.util.CollectionUtils; importorg.springframework.util.LinkedMultiValueMap; importorg.springframework.web.client.RestTemplate; importorg.springframework.web.multipart.MultipartFile; importjava.io.ByteArrayOutputStream; importjava.io.IOException; importjava.io.InputStream; importjava.io.OutputStream; importjava.lang.reflect.Type; importjava.nio.charset.Charset; importjava.util.Arrays; importjava.util.List; importjava.util.Map; importjava.util.Map.Entry; /** *@authorlxl */ publicclassFeignEncoderimplementsEncoder{ privatefinalList>converters=newRestTemplate().getMessageConverters(); privatefinalHttpHeadersmultipartHeaders=newHttpHeaders(); privatefinalHttpHeadersjsonHeaders=newHttpHeaders(); publicstaticfinalCharsetUTF_8=Charset.forName("UTF-8"); publicFeignEncoder(){ multipartHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); jsonHeaders.setContentType(MediaType.APPLICATION_JSON); } @Override publicvoidencode(Objectobject,TypebodyType,RequestTemplatetemplate)throwsEncodeException{ if(isFormRequest(bodyType)){ encodeMultipartFormRequest((Map )object,template); }else{ encodeRequest(object,jsonHeaders,template); } } privatevoidencodeMultipartFormRequest(Map formMap,RequestTemplatetemplate)throwsEncodeException{ if(CollectionUtils.isEmpty(formMap)){ thrownewEncodeException("参数不能为空."); } LinkedMultiValueMap map=newLinkedMultiValueMap<>(); for(Entry entry:formMap.entrySet()){ Objectvalue=entry.getValue(); if(isMultipartFile(value)){ map.add(entry.getKey(),encodeMultipartFile((MultipartFile)value)); }elseif(isMultipartFileArray(value)){ encodeMultipartFiles(map,entry.getKey(),Arrays.asList((MultipartFile[])value)); }else{ map.add(entry.getKey(),encodeJsonObject(value)); } } encodeRequest(map,multipartHeaders,template); } privatebooleanisMultipartFile(Objectobject){ returnobjectinstanceofMultipartFile; } privatebooleanisMultipartFileArray(Objecto){ returno!=null&&o.getClass().isArray()&&MultipartFile.class.isAssignableFrom(o.getClass().getComponentType()); } /** *设置头 *@paramfile *@return */ privateHttpEntity>encodeMultipartFile(MultipartFilefile){ HttpHeadersfilePartHeaders=newHttpHeaders(); filePartHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); try{ ResourcemultipartFileResource=newMultipartFileResource(file.getOriginalFilename(),file.getSize(),file.getInputStream()); returnnewHttpEntity<>(multipartFileResource,filePartHeaders); }catch(IOExceptionex){ thrownewEncodeException("Cannotencoderequest.",ex); } } /** *映射 *@parammap *@paramname *@paramfiles */ privatevoidencodeMultipartFiles(LinkedMultiValueMap map,Stringname,Listfiles){ HttpHeadersfilePartHeaders=newHttpHeaders(); filePartHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); try{ for(MultipartFilefile:files){ ResourcemultipartFileResource=newMultipartFileResource(file.getOriginalFilename(),file.getSize(),file.getInputStream()); map.add(name,newHttpEntity<>(multipartFileResource,filePartHeaders)); } }catch(IOExceptionex){ thrownewEncodeException("Cannotencoderequest.",ex); } } /** *{@linkHttpEntity}{@codeContent-type} *{@codeapplication/json} * *@paramo *@return */ privateHttpEntity>encodeJsonObject(Objecto){ HttpHeadersjsonPartHeaders=newHttpHeaders(); jsonPartHeaders.setContentType(MediaType.APPLICATION_JSON); returnnewHttpEntity<>(o,jsonPartHeaders); } /** *{@linkorg.springframework.web.client.RestTemplate} * *@paramvalue *@paramrequestHeaders *@paramtemplate *@throwsEncodeException */ privatevoidencodeRequest(Objectvalue,HttpHeadersrequestHeaders,RequestTemplatetemplate)throwsEncodeException{ ByteArrayOutputStreamoutputStream=newByteArrayOutputStream(); HttpOutputMessagedummyRequest=newHttpOutputMessageImpl(outputStream,requestHeaders); try{ Class>requestType=value.getClass(); MediaTyperequestContentType=requestHeaders.getContentType(); for(HttpMessageConverter>messageConverter:converters){ if(messageConverter.canWrite(requestType,requestContentType)){ ((HttpMessageConverter
Feign调用接口
@RequestLine("POST/punish/imExcel") ActionResult>imPunishExcel(@Param("file")MultipartFilefile,@Param("operatorId")IntegeroperatorId);
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。