1、文件下载
(1)使用servlet api 原生实现下载
DownloadServlet.java
package cn.qqa.controllers;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
@WebServlet
public class DownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获得当前项目路径下的下载文件(真实开发中文件名肯定是从数据中读取的)
String realPath = this.getServletContext().getRealPath("/file/1.jpg");
//根据文件路径封装成File对象,方便获取文件名
File tmpFile = new File(realPath);
//可以根据File对象获得文件名
String fileName = tmpFile.getName();
System.out.println(fileName);
//设置响应头 content-disposition:就是设置文件下载的打开方式,默认在网页打开,直接显示在网页上
//设置attachment:filename=(附件)就是为了以下载方式来打开文件
//UTF-8:防止中文乱码
resp.setHeader("content-disposition","attachment:filename=" + URLEncoder.encode(fileName,"UTF-8"));
//根据文件路径,将文件封装成文件输入流
FileInputStream fileInputStream = new FileInputStream(realPath);
int len = 0;
//声明一个1KB的缓冲区
byte[] buffer = new byte[1024];
//获取输出流
OutputStream outputStream = resp.getOutputStream();
//循环读取文件,每次读1KB,避免内存溢出
while ((len=fileInputStream.read(buffer))>0){
//往客户端写入,将缓冲区中的数据输出到客户端浏览器
outputStream.write(buffer,0,len);
}
fileInputStream.close();
}
}
(2)基于springmvc ResponseEntity的文件下载,不支持缓冲区
DownloadController.java
package cn.qqa.controllers;
import com.sun.deploy.net.HttpResponse;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
/**
* 基于servlet api的文件下载
*/
@Controller
public class DownloadController {
@RequestMapping("/download")
public String download(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//获得当前项目路径下的下载文件(真实开发中文件名肯定是从数据中读取的)
String realPath = req.getServletContext().getRealPath("/file/1.jpg");
//根据文件路径封装成File对象,方便获取文件名
File tmpFile = new File(realPath);
//可以根据File对象获得文件名
String fileName = tmpFile.getName();
System.out.println(fileName);
//设置响应头 content-disposition:就是设置文件下载的打开方式,默认在网页打开,直接显示在网页上
//设置attachment:filename=(附件)就是为了以下载方式来打开文件
//UTF-8:防止中文乱码
resp.setHeader("content-disposition","attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));
//根据文件路径,将文件封装成文件输入流
FileInputStream fileInputStream = new FileInputStream(realPath);
int len = 0;
//声明一个1KB的缓冲区
byte[] buffer = new byte[1024];
//获取输出流
OutputStream outputStream = resp.getOutputStream();
//循环读取文件,每次读1KB,避免内存溢出
while ((len=fileInputStream.read(buffer))>0){
//往客户端写入,将缓冲区中的数据输出到客户端浏览器
outputStream.write(buffer,0,len);
}
fileInputStream.close();
return null;
}
/**
* 基于springmvc ResponseEntity的文件下载 不支持缓冲区
* ResponseEntity可以定制文件的响应内容,响应头,响应状态码
*/
@RequestMapping("/responseEntity")
public ResponseEntity<String> responseEntity(){
String body = "Hello world";
HttpHeaders headers = new HttpHeaders();
headers.set("Set-Cookie","name=qqa");
return new ResponseEntity<String>(body, headers, HttpStatus.OK);
}
@RequestMapping("/download02")
public ResponseEntity<byte []> download02(HttpServletRequest req) throws Exception {
//获得当前项目路径下的下载文件(真实开发中文件名肯定是从数据中读取的)
String realPath = req.getServletContext().getRealPath("/file/1.jpg");
//根据文件路径封装成File对象,方便获取文件名
File tmpFile = new File(realPath);
//可以根据File对象获得文件名
String fileName = tmpFile.getName();
System.out.println(fileName);
//设置响应头 content-disposition:就是设置文件下载的打开方式,默认在网页打开,直接显示在网页上
//设置attachment:filename=(附件)就是为了以下载方式来打开文件
//UTF-8:防止中文乱码
HttpHeaders headers = new HttpHeaders();
headers.set("content-disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"));
//根据文件路径,将文件封装成文件输入流
FileInputStream fileInputStream = new FileInputStream(realPath);
return new ResponseEntity<byte []>(new byte[fileInputStream.available()], headers, HttpStatus.OK);
}
}
2、文件上传
Spring MVC 为文件上传提供了直接的支持,这种支持是通过即插即用的 MultipartResolver 实现的。Spring 用 Jakarta Commons FileUpload 技术实现了一个 MultipartResolver 实现类:CommonsMultipartResovler。
(1)配置pom文件,导入 MultipartResolver相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.qqa</groupId>
<artifactId>springmvc_servlet</artifactId>
<version>1.0-SNAPSHOT</version>
<!--1.加入依赖-->
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<!-- 基于Jakarta commons-fileupload 的上传支持-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
</project>
(2)UploadController.java(单文件、多文件、多线程上传)
package cn.qqa.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
/**
*
* 上传:
* 会将文件上传到3个地方
* 1.项目路径(使用项目小的情况,上传使用率低,容易丢失)
* 2.磁盘路径(需要通过虚拟目录的映射)
* 3.上传到静态资源服务器(CDN)
*/
@Controller
public class UploadController {
/**
* 基于springmvc MultipartResolver 的单文件上传
* @param desc
* @param myfile
* @return
* @throws IOException
*/
@PostMapping("/upload01")
public String upload01(String desc, MultipartFile myfile, Model model) throws IOException {
System.out.println(myfile.getOriginalFilename());
String path = "D:\\Youku Files\\"+myfile.getOriginalFilename();
File file = new File(path);
myfile.transferTo(file);
model.addAttribute("filename", myfile.getOriginalFilename());
return "success";
}
/**
* 基于springmvc MultipartResolver 的多文件上传
* @param desc
* @param myfile
* @return
* @throws IOException
*/
@PostMapping("/upload02")
public String upload02(String desc, MultipartFile [] myfile) throws IOException {
System.out.println(desc);
for(MultipartFile multipartFile:myfile){
System.out.println(multipartFile.getOriginalFilename());
String path = "D:\\Youku Files\\"+multipartFile.getOriginalFilename();
File file = new File(path);
multipartFile.transferTo(file);
}
return "success";
}
/**
* 基于springmvc MultipartResolver 的多文件上传--多线程
* 多线程上传
* @param desc
* @param myfile
* @return
* @throws IOException
*/
@PostMapping("/upload03")
public String upload03(String desc, MultipartFile [] myfile) throws IOException, InterruptedException {
System.out.println(desc);
for(MultipartFile multipartFile:myfile){
//声明线程
Thread thread = new Thread(() -> {
System.out.println(multipartFile.getOriginalFilename());
String path = "D:\\Youku Files\\" + multipartFile.getOriginalFilename();
File file = new File(path);
try {
multipartFile.transferTo(file);
}catch (IOException e){
e.printStackTrace();
}
});
thread.start();
thread.join(); //让子线程执行完再执行主线程
}
return "success";
}
}
3、index.jsp
<%--
Created by IntelliJ IDEA.
User: lenovo
Date: 2021/3/12
Time: 19:09
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Download</title>
</head>
<body>
<a href="${pageContext.request.contextPath}/download">下载文件</a>
<form enctype="multipart/form-data" action="${pageContext.request.contextPath}/upload01" method="post">
<p>文件描述:<input type="text" name="desc" /></p>
<%--<p>文件:<input type="file" name="myfile" /></p>--%>
<%--上传多个文件 设置multiple accept设置接收的文件类型--%>
<p>文件:<input type="file" name="myfile" multiple accept="image/*"/></p>
<p><input type="submit" value="上传单个文件"></p>
</form>
<hr>
<form enctype="multipart/form-data" action="${pageContext.request.contextPath}/upload03" method="post">
<p>文件描述:<input type="text" name="desc" /></p>
<%--<p>文件:<input type="file" name="myfile" /></p>--%>
<%--上传多个文件 设置multiple accept设置接收的文件类型--%>
<p>文件:<input type="file" name="myfile" multiple accept="image/*"/></p>
<p><input type="submit" value="上传多个文件"></p>
</form>
</body>
</html>
4、succes.jsp
<%--
Created by IntelliJ IDEA.
User: lenovo
Date: 2021/3/12
Time: 21:13
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Upload sucess</title>
</head>
<body>
Upload success!!!
<img src="${pageContext.request.contextPath}/img/${filename}">
</body>
</html>
5、配置虚拟目录的映射