需求:
新建一个web工程
一、springboot完成,它有一个项目名 Project
准备一份upload.html
- 上传
1.1 有一个文件上传表单,点击上传一个文件到服务器中,服务器将它存在一个文件夹中。
1.2 上传失败,转发回到upload.html
1.3 上传成功,重定向到download.html,并将需要下载的文件名传送过去
准备一份download.html
2. 下载
点击下载,将前面传送过来的文件又下载下来
注意,下载的文件名不是写死的,和刚才上传的文件名是同名的
一、项目目录截图
二、准备一个拦截器interceptor
package com.example.demo.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class FileInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
Object user = session.getAttribute("user");
if (user != null){
return true;//登录
}
return false;//游客
}
}
三、一个mvc配置文件
package com.example.demo.config;
import com.example.demo.interceptor.FileInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;
@Configuration/*让它成为配置文件 相当于springmvc.xml*/
public class MvcConfig implements WebMvcConfigurer {
@Value("${fileupload.pathname}")
private String path;
@Override
public void addInterceptors(InterceptorRegistry registry) {/*注册 相当于<mvc:interceptors>标签*/
InterceptorRegistration ir = registry.addInterceptor(new FileInterceptor());//相当于<mvc:interceptor bean标签
ir.addPathPatterns("/**");//增加路径映射 要拦截的 相当于<mvc:mapping>标签
ir.excludePathPatterns("/js/**","/img/**","/css/**","/login","/upload","/download","/xiazai");//放行的 相当于<mvc:exclude-mapping>标签
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
ResourceHandlerRegistration rhr = registry.addResourceHandler("/upload/**");
rhr.addResourceLocations("file:" + path + "\\");//必须在前面加file:,保险起见,在后面加个\\
}
}
四、一个下载工具类 DownloadUtil
package com.example.demo.util;
import sun.misc.BASE64Encoder;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
/**
* 下载工具类
*/
public class DownloadUtil {
/**
* 获取中文的编码(英文保持不变)
* @param filename 原生的中文文件名
* @param agent 来自请求的浏览器信息
* @return
* @throws UnsupportedEncodingException
*/
public static String filenameEncoding(String filename, String agent) throws UnsupportedEncodingException {
// 根据不同的客户端进行不同的编码
if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}
五、web层 FileController
我觉得难点就是如何获取上传的文件名进行下载,我这边用了不太好的一个方法,用了list去存取,声明在全局变量上,老师说可以用RESTFUL风格直接在路径上传文件名,但我没搞出来,先这样吧。
package com.example.demo.web;
import com.example.demo.util.DownloadUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
@Controller
public class FileController {
private List list = new ArrayList();
/*模拟登录*/
@RequestMapping("/login")
public String login(){
return "upload";
}
@RequestMapping("/xiazai")
public String xiazai(){
return "download";
}
/*文件上传*/
@RequestMapping("/upload")
public String upload(Model model,MultipartFile pic,
@Value("${fileupload.pathname}") String path) throws IOException {
if (!pic.isEmpty()){
pic.transferTo(new File(path,pic.getOriginalFilename()));
list.add(pic.getOriginalFilename());
return "redirect:/xiazai";
}else {
model.addAttribute("tip","上传失败,请重新选择文件。");
return "upload";
}
}
/*文件下载*/
@RequestMapping("/download")
public void download( HttpServletResponse resp,
@RequestHeader("User-Agent") String userAgent,@Value("${fileupload.pathname}") String path) throws Exception {
String filename = (String) list.get(list.size()-1);
String filenameEncoding = DownloadUtil.filenameEncoding(filename, userAgent);
resp.setHeader("Content-Disposition","attachment;filename="+filenameEncoding);
InputStream is = new FileInputStream(path + "\\"+ filename);
OutputStream os = resp.getOutputStream();
byte[] buf = new byte[1024];
int len = -1;
while ((len = is.read(buf)) != -1){
os.write(buf,0,len);
}
os.flush();
os.close();
is.close();
}
}
DemoApplication和pom.xml是框架自动生成的,就不复制过来了。application.properties里加一句话:
fileupload.pathname=d:\upload
然后在D盘下再手动建一个upload的文件夹,用来存放上传的文件。
六、准备两个页面
download.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--文件下载-->
<p>
<a th:href="@{/download}">点我下载</a>
</p>
</body>
</html>
upload.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>文件上传</h2>
<hr>
<form th:action="@{/upload}" method="post" enctype="multipart/form-data">
<p>文件: <input type="file" name="pic"></p>
<p><input type="submit" value="提交"></p>
</form>
<p style="color:red;" th:text="${tip}"></p>
</body>
</html>