SpringMVC-文件上传下载

为了能上传文件,必须将表单的 method 设置为 POST,并将 enctype 设置为 multipart/form-data。这样浏览器会采用二进制流的方式来处理表单数据。

有两种方式来进行文件上传:

  • 利用 Servlet 3.0 及更高版本的支持,但这种上传需要在 Servlet 中完成。
  • SpringMVC 中使用 MultipartFile 对象,该接口依赖于Apache Commons FileUpload 组件,因此需要引入 commons-fileupload

在 HTML5之前,想要上传多个文件,就必须使用多个文件 input 元素。但是在 HTML5 中编写以下任意一行代码,即可生成一个按钮选择多个文件:

1
2
3
4
><input type="file" name="fileName" multiple/>
><input type="file" name="fileName" multiple="multiple"/>
><input type="file" name="fileName" multiple=""/>
>

使用 SpringMVC 提供文件上传支持

在负责上传的表单设置编码为 “multipart/form-data”:

1
2
3
4
<form action="upload" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit" value="上传"/>
</form>

在请求方法中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@RequestMapping(value = "/uploadFiles")
public String uploadFile(HttpServletRequest request, @RequestParam("files") MultipartFile file) throws IOException
{
//如果上传文件非空,写入上传路径
if (!file.isEmpty())
{
//获取保存路径
String savePath = request.getSession().getServletContext().getRealPath("/uploadFiles/");
//上传文件名
String uploadFileName = file.getOriginalFilename();
File filepath=new File(savePath,uploadFileName);

if (!filepath.getParentFile().exists())
{
filepath.getParentFile().mkdir();
}
file.transferTo(new File(savePath+File.separator+uploadFileName));
request.setAttribute("message","文件上传成功");
} else
{
request.setAttribute("message","文件上传异常");
}
return "fileUpload";
}

要使用 SpringMVC 的文件上传功能,还需要在配置文件中配置 MultipartResolver:

1
2
3
4
5
6
7
8
9
10
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 上传文件大小上限,单位为字节 -->
<property name="maxUploadSize">
<value>10485760</value>
</property>
<!-- 请求的编码格式,必须和 JSP 的 pageEncoding 属性一致,以便正确读取表单的内容,默认为 ISO-8859-1 -->
<property name="defaultEncoding">
<value>UTF-8</value>
</property>
</bean>

MultipartFile 对象中的常用方法有:

  • byte[] getBytes():获取文件数据。
  • String getContentType():获取文件 MIME 类型,如 image/jpeg 等。
  • InputStream getInputStream():获取文件流。
  • String getName():获取表单中文件组件的名字。
  • String getOriginalFilename():获取上传文件的原名。
  • long getSiez():获取文件的字节大小,单位为 byte。
  • boolean isEmpty():是否有上传的文件。
  • void transferTo(File dest):将上传文件保存到一个目标文件中。

利用 Servlet 3 及更高版本上传文件

利用 Servlet3 进行文件上传,需要在 web.xml 中对 servlet 元素进行改造,

1
2
3
4
5
6
7
8
<servlet>
.....
<multipart-config>
<max-file-size>20848820</max-file-size>
<max-request-size>418018841</max-request-size>
<file-size-threshold>1048576</file-size-threshold>
</multipart-config>
</servlet>

@MultipartConfig 有如下可选属性:

  • maxFileSize:上传文件的最大容量,默认值为 -1,表示没有限制。大于指定值的文件将会被拒绝。
  • maxRequestSize:表示多部分 HTTP 请求允许的最大容量,默认值为 -1,表示没有限制。
  • location:表示在 Part 调用 write 方法时,要将已上传的文件保存到硬盘中的位置。
  • fileSizeThreshold:上传文件超出这个容量界限时,会被写入硬盘。

此外,还需要在 SpringMVC 配置文件中使用一个不同的多部分解析器:

1
2
<!-- 设置一个多部分解析器来进行基于 Servlet3 的文件上传 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"/>

客户端上传

在 Servlet 中进行文件上传并不能显示上传的进度,或者显示已经成功上传的文件数量,用户体验很差。因此HTML5 在其 DOM 中添加了一个 File API,允许访问本地文件,通过 JavaScript 和该 File API 来提供报告上传进度的进度条。

(待补充)

文件下载

对于一些保存在应用程序目录外,或者是保存在某一个数据库中,或者有时需要控制它的访问权限,防止其他网站交叉引用的资源,可以通过编程来发送。通过编程进行的文件下载,可以有选择地将文件发送到浏览器。

通过编程把一个文件发送到浏览器,需要在控制器完成以下工作:

  1. 对请求处理方法使用 void 返回类型,并在方法中添加 HTTPServletResponse 参数。
  2. 将响应的内容类型设置为文件的内容类型,例如 response.setContentType("application/pdf"),如果不清楚内容类型,并且希望浏览器始终显示Save As(另存为) 对话框,可以将 ContentType 设置为 APPLICATION_OCTET_STREAM
  3. 添加一个名为 Content-Disposition 的 HTTP 响应标题,并赋值 attachment;filename=fileName,这里 fileName 默认是文件名,通常与文件同名。