HttpServletResponse对象继承了ServletResponse接口,下面利用response对象实现下载的功能。
单个文件的下载
package com.dongmu.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
public class ResponseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String realpath = getServletContext().getRealPath("/");
//D:\word文档\电子版练习册\JAVA\02-WEB前端\kuangstudy\response\target\response-1.0-SNAPSHOT\
//这个getRealPath方法可以获得项目的绝对路径,
// System.out.println(realpath);
String filename = "壁纸.jpg";
//设置文件头:最后一个参数是设置下载文件名
response.setHeader("Content-Disposition", "attachment;fileName="+filename);
FileInputStream inputStream = new FileInputStream(realpath+"static/17.jpg");
byte[] bytes = new byte[1024];
int len =0;
//用response对象获取输出流
ServletOutputStream outputStream = response.getOutputStream();
while ((len=inputStream.read(bytes))>0){
outputStream.write(bytes,0,len);
}
inputStream.close();
outputStream.close();
}
}
String realpath = getServletContext().getRealPath("/");
获得的是:D:\word文档\电子版练习册\JAVA\02-WEB前端\kuangstudy\response\target\response-1.0-SNAPSHOT\
这个getRealPath方法可以获得项目的绝对路径,可以看一下我项目的目录结构,它所得到的就是项目打包之后webapp对应的路径。
但是这里有一个问题,就是我的文件名是中文,那么下载的时候就出现无法获取的现象,如下图
解决方案:
把代码改成:response.setHeader("Content-Disposition", "attachment;fileName="+ URLEncoder.encode(filename,"utf-8"));
原因:URLEncoder编码
客户端在进行网页请求的时候,网址中可能会包含非ASCII码形式的内容,比如中文。
而直接把中文放到网址中请求是不允许的,所以需要用URLEncoder编码地址,
将网址中的非ASCII码内容转换成可以传输的字符
编码原理:
1、将需要转换的内容(ASCII码形式之外的内容),用十六进制表示法转换出来,并在之前加上%开头
eg: 0x9c URLEncoder --> %9c
2、内容中的空格‘ ’ ,全部用+代替
3、注:与Hex不同,Hex是将所有的字符转换为16进制表示,而URLEncoder是将ASCII码集之外的转换为%加上相应的16进制,而ASCII码集内的字符不进行处理
多个文件的打包下载
前端测试html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/download">
请输入下载文件的地址:<br>
<input type="text" name="filePath">
<br>
<input type="submit" value="下载">
</form>
<br>
<hr>
<br>
<form action="http://localhost:8080/downloads">
请输入下载多个文件的地址:<br>
<input type="text" name="filePath">
<br>
<input type="text" name="filePath">
<br>
<input type="submit" value="下载">
</form>
</body>
</html>
后端实现
@RequestMapping("/downloads")
public void downloads(@RequestParam("filePath") String[] filePaths, HttpServletResponse response){
String zipName = "打包文件.zip";
ArrayList<String> fileList = new ArrayList<>(Arrays.asList(filePaths));
ZipOutputStream zos = null;
try {
response.setContentType("application/x-download ");
response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(zipName, "UTF-8"));
zos = new ZipOutputStream(response.getOutputStream());
downloadTolocal(zos, fileList);
response.flushBuffer();
} catch (IOException e) {
e.printStackTrace();
}
}
// 打包压缩
private void downloadTolocal(ZipOutputStream zos, ArrayList<String> fileList) throws IOException {
InputStream input = null;
for (String filePath : fileList) {
File file = new File(filePath);
// 一个文件对应一个ZipEntry
ZipEntry zipEntry = new ZipEntry(file.getName());
input = new FileInputStream(file);
zos.putNextEntry(zipEntry);
IOUtils.copy(input, zos);
}
zos.close();
input.close();
}
实验成功