springMVC框架中对上传下载做了一些封装,那么我们想要使用的话,就得摸清其中的一些套路,废话少说,直接写实现过程吧,博文分三个部分记录:
- 单文件上传
- 多文件上传 (其中有好几种场景,具体看下面记录)
- 文件下载
公共配置代码部分 (上述三个部分都需要用到的配置):
1、导jar包:
引入核心jar:commons-fileupload、 commons-io。
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
2、在springmvc-servlet.xml文件中配置文件上传解析器
<!-- 配置文件上传解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置总的上传文件大小为200M (200* 1024 *1024 大约是下面的数字) -->
<property name="maxUploadSize" value="200000000"></property>
<!-- 缓存最大设置为4kb -->
<property name="maxInMemorySize" value="4096"></property>
<property name="defaultEncoding" value="utf-8"></property>
</bean>
单文件上传场景:
3、写单文件上传的jsp页面 upload.jsp:
1、method必须配置为 post; 2、enctype必须配置为 multipart/form-data;
<form action="../upload/upload.action" method="post" enctype="multipart/form-data" >
<input type="file" name="uploadfile">
<input type="submit" value="上传">
</form>
4、写文件上传的控制层程序:
方法中 使用MultipartFile 对象接收前台上传过来的文件,形参名称(这里是uplaodfile )必须与表单元素file的名称一致; 另外,没有选择上传的文件,MultipartFile对象也不是null,可以通过getSize方法判断是否有上传文件
@Controller
@RequestMapping(value="/upload/")
public class UploadController {
@RequestMapping(value="upload.action")
public String upload(MultipartFile uploadfile, HttpServletRequest request, Map<String, Object> map){
if(uploadfile.getSize() > 0)
{
// 获取上传文件的名称(带后缀,如xx.jpg)
String filename = uploadfile.getOriginalFilename();
// 指定文件上传的目录
String toFilePath = request.getServletContext().getRealPath("/resource/");
File toFile = new File(toFilePath);
// 创建文件夹
if(!toFile.exists()){
toFile.mkdirs();
}
// 创建目标文件
File destFile = new File(toFile, filename);
try {
// 上传文件
uploadfile.transferTo(destFile);
}
catch (Exception e)
{
e.printStackTrace();
}
map.put("upload", "upload-success");
return "upload/upload-success";
}else{
map.put("upload", "未选择上传文件");
return "upload/upload-error";
}
}
}
多文件上传场景1
3、写多文件上传 jsp页面:
1、method必须配置为 post; 2、enctype必须配置为 multipart/form-data;
<form action="../upload/uploads.action" method="post" enctype="multipart/form-data">
<input type="file" name="uploadfile"><br>
<input type="file" name="uploadfile">
<input type="text" value="上传">
</form>
4、写多文件上传控制层程序
方法中使用的MulitpartFile[] 接受前台页面上传过来的多个文件, 在下面的形参中 uploadfile 对应页面中file类型input标签的name属性,但是,框架只会将一个文件封装在一个MulitpartFile 对象中,并不会把多个文件封装进一个MultipartFile[] 数组中, 此时如果直接使用此数组,会报:org.springframework.web.multipart.MultipartFile;.<init>();
此时:需要用@RequestParam校正参数,如下代码中示范,(当然,因为这里参数名与MultipartFile对象名一致,也可以简写成@RequestParam)
@RequestMapping(value="uploads.action")
public String uploads(@RequestParam("uploadfile") MultipartFile[] uploadfile, HttpSession session){
try{
for(MultipartFile file : uploadfile){
if(file.getSize() > 0){
String filename = file.getOriginalFilename();
String toFilePath = session.getServletContext().getRealPath("/resource/");
File toFile = new File(toFilePath);
if(!toFile.exists()){
toFile.mkdirs();
}
File destFile = new File(toFile,filename);
file.transferTo(destFile);
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
// 在Demo中没有考虑异常处理情况了
return "upload/upload-success";
}
多文件上传场景2
3、写多文件上传 jsp 页面
1、method必须配置为 post; 2、enctype必须配置为 multipart/form-data;
<form action="../upload/uploads1.action" method="post" enctype="multipart/form-data">
<!-- 一个input中选个多个文件的多文件上传场景, 加上属性 multiple 即可 -->
<input type="file" name="uploadfile1" multiple><br>
<!-- 一个文件选择一个文件的多文件上传场景 -->
<input type="file" name="uploadfile2">
<input type="file" name="uploadfile2">
<!-- 单个文件上传场景 -->
<input type="file" name="uploadfile3">
<input type="submit" value="上传">
</form>
4、写多文件上传的控制层程序
在下面的控制层方法中,不管是单个上传还是多个上传,都使用 MulitpartFile[] 接收前台页面上传的文件
@RequestMapping(value="uploads1.action")
public String uploads1(@RequestParam MultipartFile[] uploadfile1,
@RequestParam MultipartFile[] uploadfile2,
@RequestParam MultipartFile[] uploadfile3,
HttpSession session){
String toFilePath = session.getServletContext().getRealPath("/resource/");
try{
for(MultipartFile file : uploadfile1){
uploadFile(toFilePath, file);
}
for(MultipartFile file : uploadfile2){
uploadFile(toFilePath, file);
}
for(MultipartFile file : uploadfile3){
uploadFile(toFilePath, file);
}
}
catch (Exception e)
{
e.printStackTrace();
}
// 在Demo中没有考虑异常处理情况了
return "upload/upload-success";
}
public void uploadFile(String toFilePath, MultipartFile file) throws IllegalStateException, IOException{
if(file.getSize() > 0){
String filename = file.getOriginalFilename();
File toFile = new File(toFilePath);
if(!toFile.exists()){
toFile.mkdirs();
}
File destFile = new File(toFile,filename);
file.transferTo(destFile);
}
}
文件下载
3、写文件下载 jsp 页面:
<!-- 这个做Demo测试,把文件的下载写死了,,文件路径也在后台代码中指定,项目中看实际配置 -->
<a href="../upload/download.action?filename=day1.txt">下载</a>
4、写文件下载控制层程序:
常规下载方法(filename的传值是springMVC中支持的):
@RequestMapping(value="download.action")
public void download(String filename,HttpServletRequest request, HttpServletResponse response){
//设置下载的文件的编码格式
response.setCharacterEncoding("utf-8");
//设置文件的类型
response.setContentType("multipart/form-data");
//设置下载的文件的文件名称
response.setHeader("Content-Disposition", "attachment;filename="+filename);
//获取目标文件所在的文件夹路径
String toPath = request.getServletContext().getRealPath("/resource/");
//创建目标文件的输入流对象
File toFile = new File(toPath,filename);
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(toFile);
//加载响应对象的输出流对象
os = response.getOutputStream();
int len = 0;
byte[] buffer = new byte[1024];
while((len=is.read(buffer))>0){
os.write(buffer, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
os.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
在springMVC中, 对文件下载提供的ResponseEntity类型:
// Demo代码写的很糙, 实际项目中,一些公用的代码可以写到工具类中,比如获取byte数组等
@RequestMapping(value="download1.action")
public ResponseEntity<byte[]> download(String filename, HttpServletRequest request)
{
String toPath = request.getServletContext().getRealPath("/resource/");
InputStream is = null;
try {
File toFile = new File(toPath, filename);
is = new FileInputStream(toFile);
byte[] fileBody = new byte[is.available()];
// 获取文件的字符信息数组
is.read(fileBody);
HttpHeaders header = new HttpHeaders();
header.add("Content-Disposition", "attachment;filename="+filename);
HttpStatus statusCode = HttpStatus.CREATED;
ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(fileBody, header, statusCode);
return entity;
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}finally{
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
贴一下Demo的工程目录结构: