使用Feign实现微服务间文件传输
程序员文章站
2024-02-24 11:07:52
在很多时候我们会遇到微服务之间文件传输,很多时候我们可以通过序列化等方式解决(如图片等)。
最近项目中有个excel上传,以及多媒体文件上传,直接报错。
也试了2种解决...
在很多时候我们会遇到微服务之间文件传输,很多时候我们可以通过序列化等方式解决(如图片等)。
最近项目中有个excel上传,以及多媒体文件上传,直接报错。
也试了2种解决方式,都不可行。
1.写一个文件encoder解析器,会出现其他的rest请求出现encoder错误
2.springcloud feign有一个规范,不可以传输2个对象,可以是一个对象带几个参数方式。
那么我们现在需要一种方式,不配置全局的解析器,而是通过feign builder 去管理上传文件,这种方式管理起来也较为方便。
引用包
<dependency> <groupid>com.netflix.feign</groupid> <artifactid>feign-core</artifactid> <version>8.17.0</version> </dependency> <dependency> <groupid>com.netflix.feign</groupid> <artifactid>feign-jackson</artifactid> <version>8.17.0</version> </dependency> <dependency> <groupid>com.netflix.feign</groupid> <artifactid>feign-slf4j</artifactid> <version>8.17.0</version> </dependency>
调用方式
@apioperation(value = "上传excel", notes = "上传excel") @requestmapping(value = "/imexcel", method = requestmethod.post, produces = request_headers) public actionresult imexcel(@requestbody multipartfile file,@requestparam("operatorid") integer operatorid){ if(file == null || file.isempty()|| operatorid==null) return new actionresult<>(resulttype.bad_request,"文件与操作用户id都不能为空"); string filename = file.getoriginalfilename(); if (!filename.matches("^.+\\.(?i)(xls)$") && !filename.matches("^.+\\.(?i)(xlsx)$")) { return new actionresult<>(resulttype.bad_request,"上传文件格式错误,请上传后缀为.xls或.xlsx的文件"); } feign.builder encoder = feign.builder() .decoder(new jacksondecoder()) .encoder(new feignencoder()); fileupload complainfileupload = encoder.target(fileupload.class,label_url); return complainfileupload.imcomplainexcel(file,operatorid); }
文件encode
import feign.requesttemplate; import feign.codec.encodeexception; import feign.codec.encoder; import org.springframework.core.io.inputstreamresource; import org.springframework.core.io.resource; import org.springframework.http.httpentity; import org.springframework.http.httpheaders; import org.springframework.http.httpoutputmessage; import org.springframework.http.mediatype; import org.springframework.http.converter.httpmessageconverter; import org.springframework.util.collectionutils; import org.springframework.util.linkedmultivaluemap; import org.springframework.web.client.resttemplate; import org.springframework.web.multipart.multipartfile; import java.io.bytearrayoutputstream; import java.io.ioexception; import java.io.inputstream; import java.io.outputstream; import java.lang.reflect.type; import java.nio.charset.charset; import java.util.arrays; import java.util.list; import java.util.map; import java.util.map.entry; /** * @author lxl */ public class feignencoder implements encoder { private final list<httpmessageconverter<?>> converters = new resttemplate().getmessageconverters(); private final httpheaders multipartheaders = new httpheaders(); private final httpheaders jsonheaders = new httpheaders(); public static final charset utf_8 = charset.forname("utf-8"); public feignencoder() { multipartheaders.setcontenttype(mediatype.multipart_form_data); jsonheaders.setcontenttype(mediatype.application_json); } @override public void encode(object object, type bodytype, requesttemplate template) throws encodeexception { if (isformrequest(bodytype)) { encodemultipartformrequest((map<string, ?>) object, template); } else { encoderequest(object, jsonheaders, template); } } private void encodemultipartformrequest(map<string, ?> formmap, requesttemplate template) throws encodeexception { if (collectionutils.isempty(formmap)) { throw new encodeexception("参数不能为空."); } linkedmultivaluemap<string, object> map = new linkedmultivaluemap<>(); for (entry<string, ?> entry : formmap.entryset()) { object value = entry.getvalue(); if (ismultipartfile(value)) { map.add(entry.getkey(), encodemultipartfile((multipartfile) value)); } else if (ismultipartfilearray(value)) { encodemultipartfiles(map, entry.getkey(), arrays.aslist((multipartfile[]) value)); } else { map.add(entry.getkey(), encodejsonobject(value)); } } encoderequest(map, multipartheaders, template); } private boolean ismultipartfile(object object) { return object instanceof multipartfile; } private boolean ismultipartfilearray(object o) { return o != null && o.getclass().isarray() && multipartfile.class.isassignablefrom(o.getclass().getcomponenttype()); } /** * 设置头 * @param file * @return */ private httpentity<?> encodemultipartfile(multipartfile file) { httpheaders filepartheaders = new httpheaders(); filepartheaders.setcontenttype(mediatype.application_octet_stream); try { resource multipartfileresource = new multipartfileresource(file.getoriginalfilename(), file.getsize(), file.getinputstream()); return new httpentity<>(multipartfileresource, filepartheaders); } catch (ioexception ex) { throw new encodeexception("cannot encode request.", ex); } } /** * 映射 * @param map * @param name * @param files */ private void encodemultipartfiles(linkedmultivaluemap<string, object> map, string name, list<? extends multipartfile> files) { httpheaders filepartheaders = new httpheaders(); filepartheaders.setcontenttype(mediatype.application_octet_stream); try { for (multipartfile file : files) { resource multipartfileresource = new multipartfileresource(file.getoriginalfilename(), file.getsize(), file.getinputstream()); map.add(name, new httpentity<>(multipartfileresource, filepartheaders)); } } catch (ioexception ex) { throw new encodeexception("cannot encode request.", ex); } } /** * {@link httpentity} {@code content-type} * {@code application/json} * * @param o * @return */ private httpentity<?> encodejsonobject(object o) { httpheaders jsonpartheaders = new httpheaders(); jsonpartheaders.setcontenttype(mediatype.application_json); return new httpentity<>(o, jsonpartheaders); } /** * {@link org.springframework.web.client.resttemplate} * * @param value * @param requestheaders * @param template * @throws encodeexception */ private void encoderequest(object value, httpheaders requestheaders, requesttemplate template) throws encodeexception { bytearrayoutputstream outputstream = new bytearrayoutputstream(); httpoutputmessage dummyrequest = new httpoutputmessageimpl(outputstream, requestheaders); try { class<?> requesttype = value.getclass(); mediatype requestcontenttype = requestheaders.getcontenttype(); for (httpmessageconverter<?> messageconverter : converters) { if (messageconverter.canwrite(requesttype, requestcontenttype)) { ((httpmessageconverter<object>) messageconverter).write( value, requestcontenttype, dummyrequest); break; } } } catch (ioexception ex) { throw new encodeexception("cannot encode request.", ex); } httpheaders headers = dummyrequest.getheaders(); if (headers != null) { for (entry<string, list<string>> entry : headers.entryset()) { template.header(entry.getkey(), entry.getvalue()); } } /* 使用bytearray方式传输 */ template.body(outputstream.tobytearray(), utf_8); } /** * {@link org.springframework.http.httpoutputmessage} * {@link org.springframework.http.converter.httpmessageconverter} */ private class httpoutputmessageimpl implements httpoutputmessage { private final outputstream body; private final httpheaders headers; public httpoutputmessageimpl(outputstream body, httpheaders headers) { this.body = body; this.headers = headers; } @override public outputstream getbody() throws ioexception { return body; } @override public httpheaders getheaders() { return headers; } } static boolean isformrequest(type type) { return map_string_wildcard.equals(type); } static class multipartfileresource extends inputstreamresource { private final string filename; private final long size; public multipartfileresource(string filename, long size, inputstream inputstream) { super(inputstream); this.size = size; this.filename = filename; } @override public string getfilename() { return this.filename; } @override public inputstream getinputstream() throws ioexception, illegalstateexception { return super.getinputstream(); //to change body of generated methods, choose tools | templates. } @override public long contentlength() throws ioexception { return size; } } }
feign调用接口
@requestline("post /punish/imexcel") actionresult<list<string>> impunishexcel(@param("file") multipartfile file, @param("operatorid") integer operatorid);
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。