1.介绍
由于前面对于Spring中的DispatcherServlet源码解析后发现需要通过配置的方式才能使用文件上传,所以让我想起了文件的上传和下载!
2.pom依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency><!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
3.配置文件上传的解析器
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置默认的最大的上传文件大小为1024*1024*2=2M -->
<property name="maxUploadSize" value="2097152"/>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
4.创建html页面
index页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>Insert title here</title>
</head>
<body>
<h2>欢迎访问当前的index页面</h2>
<form action="hi" method="post">
使用自定义的日期格式转换器:<input type="text" name="now"/>
<input type="submit" value="提交"/>
</form>
<a href="upload.html">前往上传文件的页面</a>
<a href="download.html">前往下载文件的页面</a>
</body>
</html>
文件上传的页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>Insert title here</title>
</head>
<body>
<h2>欢迎访问当前的upload页面</h2>
<form action="upload" method="post" enctype="multipart/form-data">
选择上传文件:<input type="file" name="file"/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
文件下载的页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>Insert title here</title>
</head>
<body>
<h2>欢迎访问当前的download页面</h2>
<button onclick="location.href='download?downloadFileName=使用js后生成的二维码.png'">下载二维码文件</button>
</body>
</html>
5.这里使用的图片
6.创建工具类
web工具
import java.io.File;
import java.net.MalformedURLException;
import javax.servlet.http.HttpServletRequest;
public abstract class WebUtils {
public static final String DEFAULT_UPLOAD_DIR = "upload";
public static final String DEFAULT_DOWNLOAD_DIR = "upload";
public static File getWebFile(final String uploadDir, final String originalFilename,HttpServletRequest request) throws MalformedURLException {
String webDirPath = getWebDirPath(uploadDir,request);
final File destFile = new File(webDirPath + File.separator + originalFilename);
return destFile;
}
// 例如:/upload
public static String getWebDirPath(final String uploadDir,HttpServletRequest request) throws MalformedURLException {
String upload = uploadDir;
if (upload == null || "".equals(upload.trim())) {
upload = DEFAULT_UPLOAD_DIR;
}
final String uploadUrl = request.getServletContext().getRealPath(File.separator+upload);
return uploadUrl;
}
}
文件上传的工具
import java.io.File;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.multipart.MultipartFile;
import com.hy.spring.util.web.WebUtils;
public abstract class FileUploadUtils {
public static void saveUploadFile(final MultipartFile uploadFile, final String savePath, HttpServletRequest request)
throws IOException {
if (uploadFile == null || uploadFile.isEmpty()) {
throw new IllegalArgumentException("当前操作的文件为空,请检查文件是否上传成功!");
}
final String uploadDirPath = savePath;
final String originalFilename = uploadFile.getOriginalFilename();
final File destFile = WebUtils.getWebFile(uploadDirPath, originalFilename, request);
uploadFile.transferTo(destFile);
}
}
文件下载的工具类
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Date;
import javax.activation.MimetypesFileTypeMap;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import com.hy.spring.util.io.IOUtils;
public abstract class FileDownloadUtils {
public static void downloadFile(HttpServletResponse response, File file) throws IOException {
if (file == null || !file.exists() || !file.isFile()) {
throw new IllegalArgumentException("传入的文件有问题请检查当前的文件是否存在!");
}
// 设置默认下载的响应头
setDefaultHeader(response,file);
ServletOutputStream outputStream = response.getOutputStream();
InputStream in = IOUtils.getInputStreaByFile(file);
IOUtils.writeFile(in, outputStream);
}
//设置默认的响应流
private static void setDefaultHeader(HttpServletResponse response,File file) throws IOException {
response.setContentType(new MimetypesFileTypeMap().getContentType(file));// 设置response内容的类型
String fileName = URLEncoder.encode(file.getName(),"utf-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
response.addDateHeader("downloadTime", new Date().getTime());
}
}
io工具
public abstract class IOUtils {
// 写文件
public static void writeFile(InputStream in, OutputStream os) throws IOException {
byte[] buffer = new byte[1024];
int start = 0;
try {
while ((start = in.read(buffer)) != -1) {
os.write(buffer, 0, start);
}
} catch (IOException e) {
e.printStackTrace();
throw e;
} finally {
closeStream(in);
closeStream(os);
}
}
// 关闭输入流
public static void closeStream(InputStream in) {
if (in != null)
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭输出流
public static void closeStream(OutputStream os) {
if (os != null)
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//通过文件获取输入流
public static InputStream getInputStreaByFile(File file) throws FileNotFoundException {
return new FileInputStream(file);
}
}
这里需要注意的是:
1.文件上传中需要通过servletContext获取当前web应用的文件路径
2.文件下载的时候需要指定当前的http的content-type为上次在Nginx中的内容(二进制文件流),还需要指定当前的Content-disposition, attachment;filename=XXX
3.使用中文作为下载名的时候需要使用URLEncoder进行对中文的加码
,不然会出现中文无法解析的问题!
7.创建对应的controller
文件上传controller
/**
* @description 文件上传的controller
* @author hy
* @date 2019-10-30
*/
@RestController
public class UploadController {
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile multipartFile, HttpServletRequest request)
throws IOException {
FileUploadUtils.saveUploadFile(multipartFile, "/upload", request);
return "{\"result\":\"success\",\"option\":\"upload\"}";
}
@ExceptionHandler
public String catchException(Exception e) {
return "{\"result\":\"fail\",\"option\":\"upload\"}";
}
}
文件下载controller
@RestController
public class DownloadController {
@GetMapping("/download")
public String downloadFile(String downloadFileName, HttpServletResponse response, HttpServletRequest request)
throws IOException {
File downloadFile = WebUtils.getWebFile(WebUtils.DEFAULT_DOWNLOAD_DIR, downloadFileName, request);
FileDownloadUtils.downloadFile(response, downloadFile);
return "{\"result\":\"success\",\"option\":\"download\"}";
}
@ExceptionHandler
public String catchException(Exception e) {
return "{\"result\":\"fail\",\"option\":\"download\"}";
}
}
8.测试结果
上传文件的结果就不显示了!
9.总结
1.通过源码解析后,发现文件上传解析器必须配置在xml中
,否者就会从当前的bean工厂中找一个id为multipartResolver的文件上传解析器
2.再次使用发现了在文件上传中需要在controller中指定@RequestParam指定上传文件的名称
3.下载的时候需要注意乱码问题!
以上纯属个人见解,如有问题请联系本人!