我们定义了以下构造:
做事端生产者,将文件上传至生产者,经由处理后再发送到消费者消费者,消费生产者发送来的文件远程调用client供应消费者的远程调用做事1.2、生产者端我们大略定义了一个上传功能,如下所示
@RestControllerpublic class ProducerController { @Autowired private ConsumerFeignClient consumerFeignClient; @PostMapping("/producer/produce") public String produce(@RequestBody MultipartFile video) { System.out.println("video:"+video); //经由一系列操作,将视频转为图片... MultipartFile photo=video; consumerFeignClient.consume(photo); return "video"; }}复制代码
1.3、消费者端
在消费者端我们直接输出photo

@RestControllerpublic class ConsumerController { @PostMapping("/consumer/consume") public String consume(@RequestBody MultipartFile photo) { System.out.println("photo:"+photo); return "photo"; }}复制代码
1.4、远程调用消费者端
这里仅仅定义了远程调用接口,以供应给生产者调用
@FeignClient("service-consumer")@Repositorypublic interface ConsumerFeignClient { @PostMapping(value = "/consumer/consume",consumes = "multipart/form-data") public String consume(@RequestBody MultipartFile photo);}复制代码
1.5、问题
消费者端会输出什么?
问题的答案放在文章的末端。
2、MultipartFile接口MultipartFile实在是一个接口,个中定义供应了上传文件的各方面信息。话不多说,直接上源码。通过注释的办法解读一下各个方法的意义。
public interface MultipartFile extends InputStreamSource { //获取文件的名字,这里指的是post表单里面定义的名字 String getName(); //获取文件的原名字,这里指的是本地文件真正的名字 @Nullable String getOriginalFilename(); //文件的类型 @Nullable String getContentType(); //文件是否为空 boolean isEmpty(); //文件的大小 long getSize(); //获取文件的byte数组 byte[] getBytes() throws IOException; //以流的办法获取文件 InputStream getInputStream() throws IOException; //将其转为Resource类型,可以将其视为文件资源 default Resource getResource() { return new MultipartFileResource(this); } //将其转换为文件 void transferTo(File var1) throws IOException, IllegalStateException; //通过供应文件路径的办法将其转换为文件 default void transferTo(Path dest) throws IOException, IllegalStateException { FileCopyUtils.copy(this.getInputStream(), Files.newOutputStream(dest)); }}复制代码
个中关于供应文件根本信息的方法为:
String getName();String getOriginalFilename();String getContentType();byte[] getBytes() throws IOException; 或 InputStream getInputStream() throws IOException;这些方法描述一个文件所必须的几要素,只要有这些方法就可以得到一个文件了,其他几个方法为方便我们操作的API
3、自己写一个MultipartFile子类参考org.springframework.mock.web包下MockMultipartFile的实现,我写出了MultipartFileDto。
只须要根据接口中定义的规范,供应所需的要素即可
public class MultipartFileDto implements MultipartFile { public MultipartFileDto() { super(); } //用于储存post表单里的文件名 private String name; //用于储存文件原名 private String originalFilename; //用于储存文件类型 private String contentType; //用于储存文件数据 private byte[] content; public MultipartFileDto(String name, byte[] content) { this(name, "", null, content); } public MultipartFileDto(String name, InputStream contentStream) throws IOException { this(name, "", null, FileCopyUtils.copyToByteArray(contentStream)); } public MultipartFileDto(String name, String originalFilename, String contentType, byte[] content) { this.name = name; this.originalFilename = (originalFilename != null ? originalFilename : ""); this.contentType = contentType; this.content = (content != null ? content : new byte[0]); } public MultipartFileDto(String name, String originalFilename, String contentType, InputStream contentStream) throws IOException { this(name, originalFilename, contentType, FileCopyUtils.copyToByteArray(contentStream)); } @Override public String getName() { return this.name; } @Override public String getOriginalFilename() { return this.originalFilename; } @Override public String getContentType() { return this.contentType; } @Override public boolean isEmpty() { return (this.content.length == 0); } @Override public long getSize() { return this.content.length; } @Override public byte[] getBytes() throws IOException { return this.content; } @Override public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(this.content); } @Override public void transferTo(File dest) throws IOException, IllegalStateException { FileCopyUtils.copy(this.content, dest); }}复制代码
4、答案与精确实践4.1、答案
通过swagger上传文件进行测试,结果如下所示
生产者端:
消费者端:
可以看到,消费者端并没有获取莅临盆者供应的文件。
这是由于虽然生产者将video授予了photo变量,但本色上只是指针的改变,photo文件中通过getName()方法得到的文件名还是 “video”,自然不会自动注入了
4.2、精确实践在消费者端我们再供应一个精确的掌握器方法,利用到了上文自己定义的MultipartFileDto,将文件名改成了“photo”,使得消费者端可以成功注入。
@PostMapping("/producer/produceRight")public String produceRight(@RequestBody MultipartFile video) throws IOException { System.out.println("video:"+video); //经由一系列操作.. MultipartFile photo= new MultipartFileDto("photo","video.mp4","text/plain", video.getInputStream()); consumerFeignClient.consume(photo); return "video";}复制代码
供应swagger进行测试,消费者端正确地得到了文件:
5、小结
本文通过阅读MultipartFile接口的源码,理解了其对外供应的功能,并且自己定义了可以实现其功能的子类,从而办理了远程调用时文件获取非常的问题。
通过MultipartFile接口阅读,我们可以得到大略的结论:
接口的定义是为了定义规范,方便利用者编写实现类与调用。而一个接口所须要向外供应的API是根据实际生产需求而定的,就犹如MultipartFile接口,其核心是供应文件信息,对其进行描述。源码并没有想象中的那么晦涩,理解其核心需求能更好地帮助我们理解作者的编写意图与思路
作者:kloein链接:https://juejin.cn/post/7141689464522768392来源:稀土掘金著作权归作者所有。商业转载请联系作者得到授权,非商业转载请注明出处。