使用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(MapformMap,RequestTemplatetemplate)throwsEncodeException{
if(CollectionUtils.isEmpty(formMap)){
thrownewEncodeException("参数不能为空.");
}
LinkedMultiValueMapmap=newLinkedMultiValueMap<>();
for(Entryentry: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(LinkedMultiValueMapmap,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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。