以表单方式提交的文件上传
基本概念



额外jar包

<!--文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
spring-mvc-servlet.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">
<!-- 配置扫描的包 -->
<context:component-scan base-package="org.songwang"/>
<!--配置注解驱动 -->
<mvc:annotation-driven />
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="org.songwang.interceptor.MainInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
<!-- 文件上传和拦截器配置没有关系-->
<!--配置文件上传解析器 id 名称必须为multipartResolver-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置请求的编码格式-->
<property name="defaultEncoding" value="UTF-8"></property>
</bean>
</beans>
文件上传Controller处理逻辑
package org.songwang.controller;
import org.apache.commons.io.FileUtils;
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.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.UUID;
/**
* 〈一句话功能简述〉
* 〈功能详细描述〉
*
* @ClassName [FileUploadController]
* @Description [TODO]
* @Author [single_kitty]
* @Date [2019/1/14 22:54]
* @Version [v1.0]
**/
@Controller
public class FileUploadController {
/**
* 文件上传
*
* @return
*/
@PostMapping("/fileUpload")
public String fileUpload(@RequestParam("userName") String userName,
@RequestParam("uploadFiles") List<MultipartFile> uploadFiles,
HttpServletRequest request) {
// 判断文件是否存在
if (!uploadFiles.isEmpty() && uploadFiles.size() > 0) {
// 循环输出上传文件
for (MultipartFile file : uploadFiles){
// 获取原始的文件名称
String originalFilename = file.getOriginalFilename();
// 设置上传文件的保存目录
String uploadPath = request.getServletContext().getRealPath("/upload/");
File filePath = new File(uploadPath);
System.out.println(uploadPath);
if(!filePath.exists()){
// 如果目录不存在就创建
filePath.mkdir();
}
// 使用uuid重新命名上传文件的文件名称(上传人_uuid_文件名)
String newFileName = userName + "_"+UUID.randomUUID()+"_"+originalFilename;
try {
// 使用MultipartFile接口的方法完成文件上传到指定位置
file.transferTo(new File(filePath+"\\"+newFileName));
System.out.println(filePath+"\\"+newFileName);
} catch (IOException e) {
e.printStackTrace();
return "error";
}
}
return "success";
}
return "error";
}
@RequestMapping("/download")
public ResponseEntity<byte[]> fileDownload(HttpServletRequest request,
String filename) throws Exception{
// 指定要下载的文件所在路径
String path = request.getServletContext().getRealPath("/upload/");
// 创建该文件对象
File file = new File(path+File.separator+filename);
// 对文件名编码,防止中文文件乱码
filename = this.getFilename(request, filename);
// 设置响应头
HttpHeaders headers = new HttpHeaders();
// 通知浏览器以下载的方式打开文件
headers.setContentDispositionFormData("attachment", filename);
// 定义以流的形式下载返回文件数据
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// 使用Sring MVC框架的ResponseEntity对象封装返回下载数据
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),
headers,HttpStatus.OK);
}
/**
* 根据浏览器的不同进行编码设置,返回编码后的文件名
*/
public String getFilename(HttpServletRequest request,
String filename) throws Exception {
// IE不同版本User-Agent中出现的关键词
String[] IEBrowserKeyWords = {"MSIE", "Trident", "Edge"};
// 获取请求头代理信息
String userAgent = request.getHeader("User-Agent");
for (String keyWord : IEBrowserKeyWords) {
if (userAgent.contains(keyWord)) {
//IE内核浏览器,统一为UTF-8编码显示
return URLEncoder.encode(filename, "UTF-8");
}
}
//火狐等其它浏览器统一为ISO-8859-1编码显示
return new String(filename.getBytes("UTF-8"), "ISO-8859-1");
}
}
前端页面
<%--
Created by IntelliJ IDEA.
User: single_kitty
Date: 2019/1/14
Time: 12:01
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.net.URLEncoder" %>
<html>
<head>
<title>主页面-拦截器测试</title>
</head>
<body>
<p>${USER_SESSION.userName}</p>
<a href="${pageContext.request.contextPath}/loginOut">退出登陆</a>
<%--表单方式完成文件的上传和下载--%>
<form action="${pageContext.request.contextPath}/fileUpload"
method="post"
enctype="multipart/form-data"
"checkUpload()">
用户名:<input type="text" name="userName" id="userName"><br/>
上传文件:<<input type="file" name="uploadFiles" id="uploadFiles"><br/>
<input type="submit" value="上传">
</form>
<%--<a
href="${pageContext.request.contextPath}/download?filename=xiaobai_72165431-37c9-459c-b7a9-ce0d2077b04e_吉佑社 - 不爱又何必纠缠.mp3">
下载</a>--%>
<a href="${pageContext.request.contextPath }/download?filename=<%=
URLEncoder.encode("xiaobai_72165431-37c9-459c-b7a9-ce0d2077b04e_吉佑社 - 不爱又何必纠缠.mp3", "UTF-8")%>">
下载
</a>
<script>
function checkUpload(){
var userName = document.getElementById("userName");
var uploadFiles = document.getElementById("uploadFiles");
if(userName ==''){
alert("请输入用户名");
return false;
}
if(uploadFiles=='' || uploadFiles.length == 0){
alert("请选择上传的文件");
return false;
}
return true;
}
</script>
</body>
</html>
注意在处理中文文件名的上传下载需要注意以下几点
-
前端传递的文件名和后端的编码要一致(中文都指定为
UTF-8)<a href="${pageContext.request.contextPath }/download?filename=<%= URLEncoder.encode("xiaobai_72165431-37c9-459c-b7a9-ce0d2077b04e_吉佑社 - 不爱又何必纠缠.mp3", "UTF-8")%>"> 下载 </a> -
后端在处理中文文件名的时候,根据不同的浏览器设置不同,主要时由于ie
//..... // 对文件名编码,防止中文文件乱码 filename = this.getFilename(request, filename); //... /** * 根据浏览器的不同进行编码设置,返回编码后的文件名 */ public String getFilename(HttpServletRequest request, String filename) throws Exception { // IE不同版本User-Agent中出现的关键词 String[] IEBrowserKeyWords = {"MSIE", "Trident", "Edge"}; // 获取请求头代理信息 String userAgent = request.getHeader("User-Agent"); for (String keyWord : IEBrowserKeyWords) { if (userAgent.contains(keyWord)) { //IE内核浏览器,统一为UTF-8编码显示 return URLEncoder.encode(filename, "UTF-8"); } } //火狐等其它浏览器统一为ISO-8859-1编码显示 return new String(filename.getBytes("UTF-8"), "ISO-8859-1"); }

本文详细介绍如何在Spring MVC框架中实现文件的上传与下载功能,包括必要的依赖配置、控制器处理逻辑及前端页面设计,特别关注了中文文件名的正确处理。
1053

被折叠的 条评论
为什么被折叠?



