Spring处理multipart形式的数据

本文详细介绍了在Spring框架中处理multipart数据的方法,包括配置StandardServletMultipartResolver和CommonsMultipartResolver,以及如何在控制器中使用MultipartFile和Part对象接收上传的文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

处理multipart形式的数据

在处理文件上传之前,我们需要配置multipart解析器

配置multipart解析器

从Spring3.1开始,Spring提供了2个解析器。

  • CommonsMultipartResolver
  • StandardServletMultipartResolver:基于Servlet3.0容器。(始于Spring3.1)

通常,使用StandardServletMultipartResolver是优选的方案,但是如果使用servlet3.0之前的Servlet容器,或者使用Spring3.1之前,那么只能使用CommonsMultipartResolver。

配置StandardServletMultipartResolver
  1. 首先需要配置为bean
@Bean
public MultipartResolver multipartResolver() {
    return new StandardServletMultipartResolver();
}
  1. 然后需要做一些细节配置

有2种方式,在servlet初始化类中或xml。

在servlet初始化类配置
  • 如果我们采用Servlet初始化类的方式来配置DispatcherServlet的话,这个初始化类应该 已经实现了WebApplicationInitializer,那我们可以在Servlet registration上调 用setMultipartConfig()方法,传入一个MultipartConfigElement实例。
DispatcherServlet ds = new DispatcherServlet();
Dynamic registration = context.addServlet("appServlet", ds);
registration.addMapping("/");
registration.setMultipartConfig(
new MultipartConfigElement("/tmp/spittr/uploads"));
  • 如果我们配置DispatcherServlet的Servlet初始化类继承了Abstract AnnotationConfigDispatcherServletInitializer或AbstractDispatcher- ServletInitializer的话,我们要重写customizeRegistration方法。
@Override
protected void customizeRegistration(Dynamic registration) {
    registration.setMultipartConfig(
        new MultipartConfigElement("/tmp/spittr/uploads"));
}

上面MultipartConfigElement的构造方法的参数是临时路径,除了这个参数,还有其他参数的构造器

  • 上传文件的最大大小(单位是字节),默认是没有大小限制。
  • 请求的最大大小(单位是字节),默认是没有大小限制。
  • 文件大小达到多少时,会直接存放到临时路径中。默认是0,意思是所有的文件都存放到磁盘的临时路径中。

使用4个参数的demo如下

@Override
protected void customizeRegistration(Dynamic registration) {
    registration.setMultipartConfig(
        new MultipartConfigElement("/tmp/spittr/uploads", 2097152, 4194304, 0));
}

限制上传文件的最大大小是2MB,请求的最大大小是4MB,所有文件都保存到磁盘的临时路径中。

在xml中配置
<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/spring/application-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    <multipart-config>
        <location>/tmp/spittr/uploads</location>
        <max-file-size>2097152</max-file-size>
        <max-request-size>4194304</max-request-size>
    </multipart-config>
</servlet>

默认值和MultipartConfigElement一样,同样,是必须配置的。

配置CommonsMultipartResolver解析器

如果使用servlet3.0之前的容器或使用Spring3.1之前的版本,那么我们要使用CommonsMultipartResolver。

@Bean
public MultipartResolver multipartResolver() {
    return new CommonsMultipartResolver();
}

这时最简单的配置方式,和StandardServletMultipartResolver不同,CommonsMultipartResolver不需要强制配置临时路径。
也可以设置一些限制。

@Bean
public MultipartResolver multipartResolver() throws IOException {
    CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
    multipartResolver.setUploadTempDir(new FileSystemResource("/tmp/spittr/uploads")); //设置临时路径
    multipartResolver.setMaxUploadSize(2097152); //设置上传文件的最大大小
    multipartResolver.setMaxInMemorySize(0); //设置内存大小
    return multipartResolver;
}

CommonsMultipartResolver不能设置请求的最大大小。

处理multipart请求

我们在注册页面中添加上传图片的功能

<form method="post" enctype="multipart/form-data">
    ...

    <label>profilePicture:</label>
    <input type="file" accept="image/jpeg, image/png, image/gif" />
    
    ...
</form>

接着就是在控制器方法中获取图片参数,有3种方式:

  • byte数组
  • MultipartFile对象
  • Part对象

我们需要在方法参数上使用注解@RequestPart

使用byte[]数组方式接收

@RequestMapping(value="register", method=RequestMethod.POST)
public String processRegistration(
    @RequestPart("profilePicture") byte[] profilePicture, 
    Spitter spitter, Errors errors) {
    ...
}

如果没有选择文件,那么这个数组为空,而不是Null。

byte[]数组功能有限,使用MultipartFile可以获取更多的信息,下面是使用MultipartFile接收

@RequestMapping(value="register", method=RequestMethod.POST)
public String processRegistration(
    @RequestPart("profilePicture") MultipartFile multipartFile,
    Spitter spitter, Errors errors) {
    ...
}

@RequestPath

  • value属性:multipart/form-data请求中的参数名。

MultipartFile接口如下:

public interface MultipartFile extends InputStreamSource {
    String getName();

    @Nullable
    String getOriginalFilename();

    @Nullable
    String getContentType();

    boolean isEmpty();

    long getSize();

    byte[] getBytes() throws IOException;

    InputStream getInputStream() throws IOException;

    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));
    }
}

通过MultipartFile对象,我们不仅可以拿到文件的byte形式的数据,还能获取原始文件名、内容类型、大小,还有一个InputStream,可以用来将文件数据以流的方式进行处理。还有一个transferTo方法,能让我们可以将上传的文件保存到文件系统中。

在processRegistration方法中举例

profilePicture.transferTo(new File("/data/spittr/" + profilePicture.getOriginalFileName()));

以Part的形式接收文件

@RequestMapping(value="register", method=RequestMethod.POST)
public String processRegistration(
    @RequestPart("profilePicture") Part profilePicture,
    Spitter spitter, Errors errors) {
    ...
}

Part接口如下

package javax.servlet.http;

import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;

public interface Part {
    InputStream getInputStream() throws IOException;

    String getContentType();

    String getName();

    String getSubmittedFileName();

    long getSize();

    void write(String var1) throws IOException;

    void delete() throws IOException;

    String getHeader(String var1);

    Collection<String> getHeaders(String var1);

    Collection<String> getHeaderNames();
}

和MultipartFile的方式类似。

注意: 如果使用Part类型接收文件,那么不需要配置MultipartResolver。只有使用MultipartFile,才需要配置MultipartResolver

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值