// 文件路径 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(); } } }