文件的上传
准备工作
文件上传是项目开发中最常见的功能之一 ,springMVC 可以很好的支持文件上传,但是SpringMVC上
下文中默认没有装配MultipartResolver,因此默认情况下其不能处理文件上传工作。如果想使用Spring
的文件上传功能,则需要在上下文中配置MultipartResolver。
前端表单要求:
- 为了能上传文件,必须将表单的method设置为POST,
- 并将enctype设置为multipart/form-data。
只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器
1.index.jsp页面中
<form action="/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file">
<input type="submit" value="上传">
</form>
2.导入文件上传的jar包,commons-fileupload , Maven会自动帮我们导入他的依赖包 commons-
io包
<!--文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<!--servlet-api导入高版本的-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
3.配置bean:multipartResolver
【注意!!!这个bena的id必须为:multipartResolver , 否则上传文件会报400的错误!在这
里栽过坑,教训!】
<!--文件上传配置-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolve
r">
<!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,
默认为ISO-8859-1 -->
<property name="defaultEncoding" value="utf-8"/>
<!-- 上传文件大小上限,单位为字节(10485760=1M) -->
<property name="maxUploadSize" value="10485760"/>
<property name="maxInMemorySize" value="40960"/>
</bean>
CommonsMultipartFile 的 常用方法:
- String getOriginalFilename():获取上传文件的原名
- InputStream getInputStream():获取文件流
- void transferTo(File dest):将上传文件保存到一个目录文件中
4.Controller
@RequestMapping("/upload")
@Autowired
private BookService bookService;
public String fileUpload(@RequestParam("file")CommonsMultipartFile file, HttpServletRequest request, HttpSession session) throws IOException {
//获取原文件名
String oldFileName = file.getOriginalFilename();
//获取文件后缀
String suffix = "."+FilenameUtils.getExtension(oldFileName);
//生成新的文件名
String newFileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) +UUID.randomUUID().toString().replace("-", "") + suffix;
//获取服务器上传的文件路径
String path = session.getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()) {
realPath.mkdir();
}
System.out.println("上传文件保存地址:"+realPath);
//通过CommonsMultipartFile的transferTo方法直接写文件
file.transferTo(new File(realPath , newFileName));
String imgPath = "upload" +"/"+ newFileName;
bookService.addImg(imgPath);
session.setAttribute("fileUrl",imgPath);
return "redirect:/book/allBook";
}
小结:
文件上传的思路
1.通过Commons io 包的一些方法获取上传的文件的名字,然后截取这个名字的后缀
2.生成新的文件夹名:(再通过日期格式转换添加一个时间戳+UUID的32个字符串+后缀),以免文件名重复
3.设置一个文件上传的路径,通过new File(path) 得到一个真实路径
4.通过transferTo方法直接写文件
文件的下载
文件下载步骤:
-
获取到要下载文件的路径和文件名
-
读取文件 – InputStream
-
设置 response 响应头
-
写出文件 – OutputStream
-
文件拷贝
-
关闭流
index.jsp中
<a href="/download" target="_blank">点击下载</a>
controller中
/**
* 文件下载
*/
@RequestMapping("/download")
public void download( HttpServletRequest request,HttpServletResponse response) throws IOException {
//获取文件的信息
String path = request.getServletContext().getRealPath("/upload");
//获取图片名
String fileName = "2020092517341717a6417564d545ceb6c493b2434a2d02.jpg";
//获取文件输入流
FileInputStream is = new FileInputStream(new File(path, fileName));
//设计响应头
//附件下载----把attachment改为inline或者删除设置响应头就变成在线打开了
response.setHeader("content-disposition","attachment;fileName="+ URLEncoder.encode(fileName,"UTF-8"));
//获取响应输出流
ServletOutputStream os = response.getOutputStream();
//文件拷贝
IOUtils.copy(is,os);
//关闭流
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(os);
}
注意:附件下载----只需把attachment改为inline或者删除设置响应头就变成在线打开了
上传图片并显示图片
只需要修改controller中的东西,判断是否图片,通过获取文件的类型判断,是图片肯定前缀肯定有 image
@Controller
public class FileController {
@Autowired
private BookService bookService;
@RequestMapping("/upload")
public String fileUpload(@RequestParam("file")CommonsMultipartFile file, HttpServletRequest request, HttpSession session) throws IOException {
if (!file.isEmpty()) {
//获取文件后缀
String suffix = "."+FilenameUtils.getExtension(file.getOriginalFilename());
//生成新的文件名
String newFileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) +
UUID.randomUUID().toString().replace("-", "") + suffix;
//获取服务器上传的文件路径
String path = session.getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()) {
realPath.mkdir();
}
System.out.println("上传文件保存地址:"+realPath);
//判断是否图片,通过获取文件的类型判断,是图片肯定前缀肯定有 image
if (file.getContentType().startsWith("image")) {
//通过CommonsMultipartFile的transferTo方法直接写文件
file.transferTo(new File(realPath , newFileName));
String imgPath = "upload" +"/"+ newFileName;
//保存到数据库
bookService.addImg(imgPath);
session.setAttribute("fileUrl",imgPath);
}else {
System.out.println("请选择图片格式文件上传");
session.setAttribute("msg","请选择图片格式文件上传");
}
}
return "redirect:/book/allBook";
}
记住图片的地址:http://localhost:8080/上传的文件目录+图片名
访问路径有项目名也要加在端口号后面,我这里没有配的是/
http://localhost:8080等价于=> ${pageContext.request.contextPath}
${fileUrl}相当于上传的文件目录+图片名
<img src="http://localhost:8080/${fileUrl}" style="width: 100px;height: 40px;" alt="111">
或
<img src="${pageContext.request.contextPath}/${fileUrl}" style="width: 100px;height: 40px;" alt="111">
多文件上传和下载
index.jsp
<h1>-----------多文件上传----------</h1>
<form action="${pageContext.request.contextPath}/upload1" enctype="multipart/form-data" method="post">
<input type="file" name="file"><br>
<input type="file" name="file"><br>
<input type="file" name="file"><br>
<input type="submit" value="上传">
</form>
controller
@Controller
public class Hello{
//访问/ 跳到index.jsp页面
@RequestMapping("/")
public String a(){
return "index";
}
//多文件上传
@RequestMapping("/upload1")
public String fileUpload(@RequestParam("file") CommonsMultipartFile[] file , HttpServletRequest request, HttpSession session) throws IOException {
//上传的路径 这里是获取项目的根目录 在out目录
java.lang.String path = request.getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()) {
realPath.mkdir();
}
for(int i=0;i<file.length;i++){
//获取文件后缀
String suffix = "."+FilenameUtils.getExtension(file[i].getOriginalFilename());
//生成新的文件名
String newFileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) +UUID.randomUUID().toString().replace("-", "") + suffix;
//通过CommonsMultipartFile的transferTo方法直接写文件
file[i].transferTo(new File(realPath , newFileName));
String imgPath = "upload" +"/"+ newFileName;
session.setAttribute("fileUrl",imgPath);
session.setAttribute("fileUrl"+i,imgPath);
session.setAttribute("download1"+i,newFileName);
}
System.out.println("上传文件保存地址:"+realPath);
return "hello";
}
/**
* 文件下载
*/
@RequestMapping("/download/{img}")
public void download(@PathVariable("img") String img, HttpServletRequest request,HttpServletResponse response,HttpSession session) throws IOException {
//获取文件的信息
String path = request.getServletContext().getRealPath("/upload");
//获取图片名
String fileName = (String)session.getAttribute("download1"+img);
//获取文件输入流
FileInputStream is = new FileInputStream(new File(path, fileName));
//设计响应头
//附件下载----把attachment改为inline或者删除设置响应头就变成在线打开了
response.setHeader("content-disposition","attachment;fileName="+ URLEncoder.encode(fileName,"UTF-8"));
//获取响应输出流
ServletOutputStream os = response.getOutputStream();
//文件拷贝
IOUtils.copy(is,os);
//关闭流
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(os);
}
}
hello.jsp
<body>
<!--展示上传的路径-->
${fileUrl}<br>
<img src="http://localhost:8080/SpringMVC-01/${fileUrl0}" style="width: 200px;height: 100px;" alt="111">
<a href="${pageContext.request.contextPath}/download/0" target="_blank">点击下载</a><br>
<img src="http://localhost:8080/SpringMVC-01/${fileUrl1}" style="width: 200px;height: 100px;" alt="111">
<a href="${pageContext.request.contextPath}/download/1" target="_blank">点击下载</a><br>
<img src="http://localhost:8080/SpringMVC-01/${fileUrl2}" style="width: 200px;height: 100px;" alt="111">
<a href="${pageContext.request.contextPath}/download/2" target="_blank">点击下载</a><br>
</body>
运行访问:http://localhost:8080/SpringMVC-01/
点击上传:
小结:多文件上传与单文件上传的不同点就是,多文件上传以数组方式接收,我这里展示图片和下载图片就直接把代码写死了。
String path = session.getServletContext().getRealPath("/upload");
上传文件保存地址:D:\Tomcat\apache-tomcat-9.0.31\webapps\ROOT\upload
上传文件保存地址:D:/Tomcat/apache-tomcat-9.0.31/webapps/ROOT/WEB-INF/classes/upload
String path = ResourceUtils.getURL(“classpath:”).getPath() + “/upload”;