深入源码!详解MultipartFile

MultipartFile 和 CommonsMultipartFile的区别 一、问题发生      在学习SpringMVC框架时,视频中老师使用CommonsMultipart接受上传的文件,而我以前使用的是MultipartFile接收上传的文件,便想要知道他们的区别。 二、问题解决 查看源码文件 MultipartFile.java public interface MultipartFile extends Inp... 阅读详情

MultipartFile大家想必不陌生,在SpringMVC的控制器方法中,我们可以通过MultipartFile自动注入上传的文件。我们从一个小案例引入,深入了解下MultipartFile

1、一个小问题

此问题来自真实案例,大家可以先想想当我们通过生产者端 /producer/produce上传文件时,消费者端会输出什么

1.1、整体结构

我们定义了以下结构:

  • 服务端

    • 生产者,将文件上传至生产者,经过处理后再发送到消费者
    • 消费者,消费生产者发送来的文件
  • 远程调用client

    • 提供消费者的远程调用服务

1.2、生产者端

我们简单定义了一个上传功能,如下所示

@RestController
public 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

@RestController
public class ConsumerController {
    @PostMapping("/consumer/consume")
    public String consume(@RequestBody MultipartFile photo) {
        System.out.println("photo:"+photo);
        return "photo";
    }
}
复制代码

1.4、远程调用消费者端

这里仅仅定义了远程调用接口,以提供给生产者调用

@FeignClient("service-consumer")
@Repository
public 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接口,其核心是提供文件信息,对其进行描述。源码并没有想象中的那么晦涩,了解其核心需求能更好地帮助我们理解作者的编写意图与思路

MultipartFile来上传单个及多个文件代码示例 阅读详情

相关推荐

SpringMVC使用MultipartFile实现文件上传

主要为大家详细介绍了SpringMVC使用MultipartFile实现文件上传功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

MockMultipartFile mock文件上传

ClassPathResource resource = new ClassPathResource("XXX.js"); MockMultipartFile mfile = new MockMultipartFile("file", "XXX.js", "png", resource.getInputStream()); MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.multipart("/XX..

ISaiSai的专栏 8689

极空间NAS小白也能搞定的Gitea部署:Docker+MySQL避坑全记录

本文为极空间NAS用户提供了一份详尽的Gitea私有代码仓库部署指南。针对极空间ARM架构和图形化Docker管理的特殊性,文章重点讲解了如何通过Docker和MySQL容器进行部署,并提供了三种获取兼容镜像的实战策略,特别是利用第三方镜像站转录的方法,帮助小白用户成功搭建并初始化Gitea服务,实现私有Git托管。

weixin_28318011的博客 368

MockMultipartFile

org.springframework.mock.web Class MockMultipartFile java.lang.Object org.springframework.mock.web.MockMultipartFile All Implemented Interfaces: MultipartFile public class MockMultipartF...

stujike123456的博客 2万+

基于simulink的变压器保护仿真设计【MATLAB源码+Word文档】

电力系统变压器保护MATLAB/simulink仿真设计。纵联差动保护-过电流保护-距离保护

weixin_761237174的博客 1271

模拟滤波器的基础知识和设计

使用Python实现多种模拟滤波器

faltas的博客 3530

根据源码用HttpServletRequest获取MultipartFile的问题

问题 由于某些原因,现在需要这样的一个文件上传接口,这个接口type(String)是必传参数,photoFile(MultipartFile)是非必传参数,即一般情况下需要接受两个参数,分别为photoFile和type,但是偶尔只接受type参数,不需要起到上传作用。 按常规写法,photoFile参数的required配置设置为了false。 奈何调试时发现,photoFile的requir...

weixin_30951389的博客 6086

SQL 通过sum() over(order by ,rownum)实现财务现金日记账实例

SELECT 类型,to_char(发生日期,'yyyy-MM-dd') 发生日期,期初余额,借方金额,贷方金额, (CASE WHEN 借方金额>0 THEN '借' WHEN 贷方金额>0 THEN '贷' ELSE '平' END) 方向, sum(收支金额) over(order by 发生日期, rownum) 余额 FROM( SELECT LX 类型,账户,账号,摘要,发生日期,单据ID, ...

qq_41451794的博客 1023

Spring中的MultipartFile详解

      在Java中处理文件向来是一种不是很方便的操作,然后随着Spring框架的崛起,使用Spring框架中的MultipartFile来处理文件也是件很方便的事了,今天就为大家带来剖析MultipartFile的神秘面纱。MultipartFile本身并没有很复杂的结构,也正是他强力封装了很多便捷的api才引来很多人的使用。 一、概述      MultipartFile为org.sprin

Rocky balboa 5954

省一蓝桥杯嵌入式-09RTC实时时钟

RTC(Real-Time Clock)实时时钟,是一个独立的定时器RTC模块拥有一组连续的计数的计数器,在响应软件配置下,可提供时钟、日历、闹钟功能RTC能提供年月日时分秒等信息(可设置)在系统复位或从待机模式唤醒后,RTC的设置时间维持不变(这个我没实现,复位后时间也重置了,有能力的可以自己研究一下)持续时间跟踪:在主系统断电后或处于低功耗模式时,RTC仍继续工作,原理是有额外的电池为其供电(蓝桥杯板子没有这个备用电源,该功能无效。

qq_46392331的博客 1729

一文读懂 SAP ERP / SAP S/4HANA 里的 Price List:概念、配置、定价流程与可运行 ABAP 示例

SAP ERP/S4HANA中的Price List解析 本文系统阐述了SAP定价体系中Price List的核心概念和实现机制。Price List并非独立的价目表,而是通过条件技术(条件类型、访问序列、条件记录)与Price List Type(PLTYP)共同作用的定价维度。文章详细说明了: Price List本质上是客户主数据中的PLTYP字段,作为定价查找键使用 定价流程中条件访问序列如何利用PLTYP查找特定价格 S4HANA与ECC版本在价格维护入口的差异 实际业务中如何通过不同PLTYP实

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 660

MultipartFile和CommonsMultipartFile的区别!

MultipartFile 源码 package org.springframework.web.multipart; import java.io.File; import java.io.IOException; import java.io.InputStream; import org.springframework.core.io.InputStreamSource; public...

想好了就去做吧 即便失败了 至少这条路上留下了你的脚印 7930

建行报专版报道建设银行金融科技发展历程

经过十多年的建设,总行前中后台部门都有了自己的业务系统,但系统“部门”特征显著,渠道、客户、产品的横向整合不足,产品系统层次化、结构化、参数化程度不高,渠道支持产品快速部署以及跨渠道服务能力不足,管理分析类系统建设相对滞后,系统较弱的可扩展能力在应对高速增长的交易量时已疲态尽显,同时安全稳定运行的压力和风险日益积聚。站在新的历史起点上,科技条线将聚焦主责主业,完善信息科技管理体系,紧紧围绕安全生产中心任务,持续推动技术能力复用共享和自主可控,为全行做好金融五篇大文章,推动业务高质量发展提供技术支撑。

银行信息系统应用架构详解 385

深入理解MultipartFile,以更优雅的方式处理文件

Hello,大家好,我是Steafan_,这几天有时间我就来更新博客了,话不多说直入正题。 在Java中处理文件向来是一种不是很方便的操作,然后随着Spring框架的崛起,使用Spring框架中的MultipartFile来处理文件也是件很方便的事了,今天就为大家带来剖析MultipartFile的神秘面纱。MultipartFile本身并没有很复杂的结构,也正是他强力封装了很多便捷的...

Steafan_ 8万+

外部PLC触发VisionMaster多流程运行

上一讲,介绍了海康VisionMaster与西门子PLC1200进行S7通信。在前一讲的基础上,讲解如何通过PLC触发,实现VisionMaster的多流程运行。

haier123888的博客 4653

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

MultipartFile的属性 file.getOriginalFilename()与file.getName()的区别 MultipartFile与File互转

二、MultipartFile常用方法 三、Springboot与MultipartFile的使用 3.1 设置文件上传大小限制 3.2 Springboot上传单个文件,包含其他参数 3.3 Springboot上传多个文件,包含请求体 四、MultipartFile中transferTo方法的坑 4.1 调用tansferTo()方法后,再次获取file.getInputStream()方法时,报临时文件异常 源码分析 五、MultipartFile与File文件互转

weixin_49114503的博客 2万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Byte、File、MultipartFile之间的转换

一、byte[]转MultipartFile 需要引入jar包才能使用 pom.xml(版本可自行指定) <dependency> <groupId>org.springframework</groupId> <artifactId>spring-mock</artifactId> <version>2.0.8</version> </dependency> MockMultipartF

weixin_40300139的博客 2万+

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

彻底弄懂Java中的MultipartFile接口和File类

不管是在项目中还是日常需求,我们总是有操作文件数据的需求,Java中操作文件不可避免就要使用File类,而Spring中为我们提供了一个操作文件的接口,通过该接口我们可以获取用户上传的文件对象并写入文件系统中。这篇文章主要围绕MultipartFile接口和File类中相关方法的功能进行梳理,其中有关文件写入File对象和Path对象重点进行了剖析,希望能帮助到有需要的小伙伴~~~

荔枝当大佬的博客 1万+

file 转换MultipartFile

因为工作中的业务需要,需要将file转换为Spring专有的MultipartFile。 过程 结论过程spring通过MultipartFile来实现文件上传,查看相关的源码后,会发现原理十分简单。 首先,打开MultipartFile,发现这是一个接口,其中定义了一些关于文件的方法。同时看到此接口的实现类,分别来看这几个实现类。 打开StandardMultipartFile,发现这是一个私有

u013486840的博客 4万+

Java中的MultipartFile接口和File类

我们可以看到。

2301_78992368的博客 3739

初步理解MultipartFile[文件上传]

MultipartFile为org.springframework.web.mutipart包下的一个类,也就是说如果想使用MultipartFile这个类就必须引入spring框架,换句话说,如果想在项目中使用MultipartFile这个类,那么项目必须要使用spring框架才可以,否则无法引入这个类。MultipartFile翻译成中文来讲就是“多组件的文档”,不用太在乎他的中文含义,一般来讲使用MultipartFile这个类主要是来实现以表单的形式进行文件上传功能。

ControllerDesire 1089

深入理解 MultipartFile 处理文件

从上图的return中可以看出,返回的name值从来不是null或者空,也就是说如果使用MultipartFile来接收文件,那么@Param("uploadFile")定义的接收文件的名称则必不可少,这样才能接收到文件,如果没有定义@Param("uploadFile"),则接收不到文件。也就是说,如果你想用spring框架来实现项目中的文件上传功能,则MultipartFile可能是最合适的选择,而这里提到的多种请求方式则可以通俗理解为以表单的形式提交。该方法在实际项目开发中使用较少。

tengyuxin的博客 1万+
上一篇: 海归硕士面试3家大厂挂了2个,成功拿到字节跳动offer,分享面经
下一篇: 手把手教你用Java获取IP归属地
程序员职业指南
博客等级 码龄4年 2136粉丝 960原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值