// 文件路径 D:\ApacheServer\web_java\HelloWorld\src\com\test\TestServletDownload.java
package com.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
public class TestServletDownload {
public void testfun(HttpServletResponse response){
// 最好放在 response 所有输出之前调用,并且执行后避免再向浏览器发送其他输出流
try{
// 要下载的文件名
String fileName = "00125943U-0.jpg";
// 文件下载到客户端时文件名
String downName = "download.jpg";
// 获取项目运行根目录
// Thread.currentThread().getContextClassLoader().getResource("") 获取项目运行实际 classes 目录 这里为 file:/D:/ApacheServer/web_java/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/HelloWorld/WEB-INF/classes/
// 参数 "../../" 为取向上两级目录,这里为 file:/D:/ApacheServer/web_java/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/HelloWorld/
// .toString().substring(6) 消除返回路径中的 file:/ 字符串,这里返回路径为 D:/ApacheServer/web_java/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/HelloWorld/
String appBase = Thread.currentThread().getContextClassLoader().getResource("../../").toString().substring(6);
// 获取文件的绝对路径,这里为 D:/ApacheServer/web_java/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/HelloWorld/upload/00125943U-0.jpg。File.separator 表示目录分割斜杠
String fullFileName = appBase + "upload" + File.separator + fileName;
// 获取文件 MIME 类型
Path path = Paths.get(fullFileName);
String mimeType = Files.probeContentType(path);
// 设置文件 MIME 类型
response.setContentType(mimeType);
// 设置 Content-Disposition 响应报头,命名下载文件名称
response.setHeader("Content-Disposition"," attachment;filename=" + downName);
// 把文件读入到内存输入流中
InputStream inputStream = new FileInputStream(fullFileName);
// 创建输出流对象
ServletOutputStream outputStream = response.getOutputStream();
// 每次从输入流实际读取到的字节数
int len = 0;
// 定义一个字节数组,相当于缓存,数组长度为1024,即缓存大小为1024个字节
byte[] cache = new byte[1024];
// inputStream.read(cache)) 方法,从输入流中读取最多 cache 数组大小的字节,并将其存储在 cache 中。以整数形式返回实际读取的字节数,当文件读完时返回-1
while((len = inputStream.read(cache)) != -1){
// 每次把数组 cache 从 0 到 len 长度的内容输出到浏览器
outputStream.write(cache, 0, len);
}
// 关闭流
inputStream.close();
outputStream.close();
}catch(Exception exception) {
// 处理 Class.forName 错误
exception.printStackTrace();
}
}
}