前言
在开发网站时有时候我们需要对一些文件的上传和下载,下面提供一种基于SpringMVC的文件上传和下载Demo。
配置
这里只介绍单纯的SpringMVC的配置,对于Spring与SpringMVC之间的整合以下配置不做介绍。
web.xml
SpringMVC的配置主要是通过servlet实现的,基于Java的Web项目大部分是通过Servlet实现的,通过web.xml来实现对servlet的管理。
有Spring基础的同学应该都知道,Spring的上下文是通过Listener来读取并且实例化Bean的。而web.xml的执行顺序是按以下顺序执行的。
- context-param
- listener
- filter
- servlet
而Spring是由Listener来进行容器的初始化的,而SpringMVC是由servlet进行初始化的。
了解这个知识对项目的管理有一定的帮助,下面是web.xml的配置。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
metadata-complete="true" version="3.1">
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Spring MVC 配置
下面是关于SpringMVC的配置,如spring-mvc.xml所示。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven />
<!-- The base package need to be scan -->
<context:component-scan base-package="com.johnson.spring.mvc.file" />
</beans>
通过注解配置Bean
这里使用了注解代替xml配置的方式实现SpringMVC相关Bean的配置。
下面是通过@Configure注解对Bean进行实例化。
package com.johnson.spring.mvc.file.configure;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
public class MvcConfigure extends WebMvcConfigurerAdapter {
@Bean
public ViewResolver resourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/page/");
resolver.setSuffix(".jsp");
return resolver;
}
@Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setDefaultEncoding("utf-8");
resolver.setMaxUploadSize(100000L);
resolver.setMaxInMemorySize(40960);
return resolver;
}
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**/*").addResourceLocations("/WEB-INF/frameworks/");
}
}
具体实现
这样就完成了对于静态文件的访问、视图解析和文件解析这三个功能的配置了。接下来就可以通过@Controller配置进行web项目接口的实现了。具体由以下代码实现。使用了两种方式进行文件的上传和下载。推荐使用RequestEntity和MultipartFile的方式进行文件的上传和下载。如果在MvcConfigure中对MultipartResolver 实例化的话,在使用HttpServletRequest的方式来进行文件的上传时不需要使用CommonsMultipartResolver.resolveMultipart(request)进行转换,直接强制转换就可以了。
package com.johnson.spring.mvc.file.controller;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import com.johnson.common.util.FileUtil;
@Controller
@RequestMapping("/file")
public class FileMvcController {
private static final String DOWNLOAD_FILE_NAME = "download/Download.txt";
private static final String UPLOAD_DIR = "upload";
private final String PATH = getFilePath();
@RequestMapping()
public String index() {
return "file";
}
@RequestMapping(value = "/request-entity", method = RequestMethod.POST)
public ResponseEntity<byte[]> downloadByte() throws UnsupportedEncodingException, FileNotFoundException {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", "download.txt");
String downloadFile = FileUtil.read(PATH, DOWNLOAD_FILE_NAME);
return new ResponseEntity<>(downloadFile.getBytes(), headers, HttpStatus.OK);
}
@RequestMapping(value = "/servlet-download", method = RequestMethod.POST)
public void downloadFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("application/octet-stream");// 设置强制下载不打开
response.addHeader("Content-Disposition", "attachment;fileName=" + "download.txt");
String downloadFile = FileUtil.read(PATH, DOWNLOAD_FILE_NAME);
OutputStream os = response.getOutputStream();
os.write(downloadFile.getBytes());
os.flush();
os.close();
}
@RequestMapping(value = "/servlet-upload", method = RequestMethod.POST)
public void uploadFile(HttpServletRequest request, HttpServletResponse response)
throws IllegalStateException, IOException {
// 在MvcConfigure中实例化了bean
CommonsMultipartResolver resolver = new CommonsMultipartResolver(
request.getSession().getServletContext());
resolver.setDefaultEncoding("utf-8");
resolver.setMaxUploadSize(100000L);
resolver.setMaxInMemorySize(40960);
// 判断是否包含文件
if (resolver.isMultipart(request)) {
// 将request转换为MultipartHttpServletRequest
// 在MvcConfigure实例化CommonsMultipartResolver之后,直接强制转换就可以了
// MultipartHttpServletRequest multiRequest = resolver.resolveMultipart(request);
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
// 得到文件名列表的迭代器
Iterator<String> fileNameIterator = multiRequest.getFileNames();
while (fileNameIterator.hasNext()) {
// 根据表单内的name获取MultipartFile
MultipartFile file = multiRequest.getFile(fileNameIterator.next());
if (file != null) {
// 获取文件名
String fileName = file.getOriginalFilename();
if (fileName.trim() != "") {
// 获取存储路径
String path = PATH + File.separator + UPLOAD_DIR + File.separator + fileName;
File localFile = new File(path);
if (!localFile.exists() || localFile.isDirectory()) {
localFile.createNewFile();
}
// 写入文件
file.transferTo(localFile);
}
}
}
}
}
@RequestMapping("/multipart-file")
public void uploadFile(MultipartFile[] multipartfile) {
for (MultipartFile file : multipartfile) {
if (!file.isEmpty()) {
try {
File dir = new File(PATH + File.separator + UPLOAD_DIR);
if (!dir.exists()) {
dir.mkdirs();
}
// 拿到输出流,同时重命名上传的文件
FileOutputStream os = new FileOutputStream(
PATH + File.separator + UPLOAD_DIR + File.separator + file.getOriginalFilename());
// 拿到上传文件的输入流
InputStream in = file.getInputStream();
// 以写字节的方式写文件
int b = 0;
while ((b = in.read()) != -1) {
os.write(b);
}
os.flush();
os.close();
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private String getFilePath() {
String classpath = this.getClass().getResource("/").getPath();
File file = new File(classpath);
String webInfoPath = file.getParent();
String filePath = webInfoPath + File.separator + "file";
return filePath;
}
}
以上代码只是个简单的demo,仅供参考。
具体项目可以查看我的github地址:johnson.project