Spring MVC 中 MultipartResolver(多部件解析器)接口为文件上传提供了直接支持,此接口由于处理上传请求,将上传请求包装为可以直接获取文件的数据,方便操作。它有2个实现类:
- StandardServletMultipartResolver:是spring3.1后的产物,使用Servlet3.0标准的上传方式,不依赖于第三方包。
- CommonsMultipartResolver:使用Apache的commons-fileupload完成上传,需要依赖第三方包,可以在spring各版本使用。
单文件上传
- 下载添加相关jar包:
百度网盘下载
提取码:sl8e
将jar包添加到WebContent\WEB-INF\lib目录下,刷新项目 - 在src下的配置文件中配置CommonsMultipartResolver类
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 上传文件最大为1MB -->
<property name="maxUploadSize" value="1048576"/>
<!-- 默认字符编码为UTF-8 -->
<property name="defaultEncoding" value="UTF-8"/>
</bean>
- 在com.springmvc.controller包中新建FileUploadController类
package com.springmvc.controller;
import java.io.File;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
@Controller
public class FileUploadController {
@RequestMapping("/fileUpload")
public String fileUpload(@RequestParam(value="file", required=false)
MultipartFile file, HttpServletRequest request, ModelMap model) {
//获取项目在容器中的实际发布运行的根路径
String path = request.getSession().getServletContext().getRealPath("upload");
//获取上传文件的原名
String fileName = file.getOriginalFilename();
File targetFile = new File(path,fileName);
if(!targetFile.exists()) {
targetFile.mkdirs();
}
try {
//将上传文件保存到一个目录文件中
file.transferTo(targetFile);
} catch (Exception e) {
e.printStackTrace();
}
model.put("fileUrl",request.getContextPath()+"/upload/"+fileName);
return "success";
}
}
- 在WebContent下创建index.jsp,添加表单请求到刚才的方法中
<form action="../fileUpload" method="post" enctype="multipart/form-data">
<input type="file" name="file" value="选择文件"/><br>
<input type="submit" value="上传"/>
</form>
- 创建success.jsp,输出上传路径:
上传成功<br>
文件路径: ${requestScope.fileUrl}
运行结果:
ps:在项目发布路径下可寻找到upload文件夹,如果从来没有更改过项目的发布路径,则到工作空间的.metadata 下,.metadata\.plugins\org.eclipse.wst.server.core\temp0\wtpwebapps\下寻找upload文件夹。如果修改过,则到webapps下的项目路径中寻找。
ps:修改项目发布路径:修改Tomcat项目发布路径
多文件上传
多文件和单文件差别不是很大,主要把MultipartFile类型改为MultipartFile[ ]类型或者List<MultipartFile>这些可以存储多个元素的类型。
然后在index.jsp的文件选择中添加属性 multiple=“multiple”,这样就可以选择多个文件
<input type="file" name="files" value="选择文件" multiple="multiple"/><br>
多文件上传代码:
public String multiUpload(@RequestParam(value="files", required=false) MultipartFile[] files, HttpServletRequest request,ModelMap model) {
if(files.length>0) {
String path = request.getSession().getServletContext().getRealPath("upload");
for(MultipartFile file: files) {
String fileName = file.getOriginalFilename();
File targetFile = new File(path,fileName);
if(!targetFile.exists()) {
targetFile.mkdirs();
}
try {
file.transferTo(targetFile);
} catch (Exception e) {
e.printStackTrace();
}
}
model.put("fileUrl",request.getContextPath()+"/upload/");
return "success";
} else {
return "error";
}
}
文件下载
文件下载比较简单,直接在页面给出超链接,链接的href属性为下载文件的文件名,即可实现下载。
页面关键代码:
<a href="fileDownload?fileName=文件名">下载</a>
后台代码:
@RequestMapping("/fileDownload")
public ResponseEntity<byte[]> fileDownload(@RequestParam("fileName") String fileName,
HttpServletRequest request, Model model) throws Exception{
String path = request.getSession().getServletContext().getRealPath("/upload/");
File file = new File(path+File.separator+fileName);
//设置响应头
HttpHeaders headers = new HttpHeaders();
//下载显示的文件名为UTF-8编码
String downloadFileName = new String(fileName.getBytes("UTF-8"));
//以下载方式attachment打开文件
headers.setContentDispositionFormData("attachment", downloadFileName);
//以二进制流数据下载返回文件数据
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//使用spring mvc的ResponseEntity对象封装返回下载数据
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers,HttpStatus.CREATED);
}
上面这种是springmvc的默认下载方式。在下载过程中它会把整个文件放入响应实体中,对于大文件会造成假死现象。所以我们在下载大文件时可以选择下面这种流的方式下载。
@RequestMapping(value = "/download_normal")
public void download_normal(HttpServletResponse resp, HttpSession session, @RequestParam("fileName") String fileName)
throws Exception {
String downloadFielName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");
// 设置响应的内容类型为流的方式
resp.setContentType("application/octet-stream");
// 让服务器告诉浏览器它发送的数据属于什么文件类型(流)
resp.setHeader("content-type", "application/octet-stream");
// 告诉浏览器这个文件的类型和名字(attachment--以附件的方式)
resp.setHeader("Content-Disposition", "attachment;filename=" + downloadFielName);
String realPath = session.getServletContext().getRealPath("/upload/");
FileInputStream fis = new FileInputStream(realPath + downloadFielName);
ServletOutputStream os = resp.getOutputStream();
int len = 0;
// 自定义缓冲区,缓冲区大小为1024k(每次读取多少内容)
byte[] b = new byte[1024];
// 读取到的字节数辅助给len
while ((len = fis.read(b)) != -1) {
// 写字节数组里面的内容(读多少写多少)
os.write(b, 0, len);
}
os.close();
fis.close();
}