一、文件下载案例需求
1、页面显示超链接
2、点击超链接后弹出下载提示框
3、完成图片文件下载
二、注意
如果超链接的href属性直接写为工作空间里的图片路径,点击超链接后,浏览器是不会弹出下载提示框的,因为浏览器会默认解析图片然后进行展示!
而如果是像视频之类的,浏览器就默认不解析视频,会给你弹出一个下载提示!
也就是说,如果超链接指向的资源可以被浏览器解析,则在浏览器中直接展示,如果不能被浏览器直接解析,就会弹出下载提示框!
所以!要弹出下载提示框下载图片的操作就比较麻烦一点!
三、分析
使用响应头设置资源的打开方式:
content-disposition:attachment;filename=xxx
注意:xxx是将来下载提示框里展示的文件的名称
四、步骤
1、编写前端页面
编辑超链接的href属性值,使其指向downloadServlet!
但要注意:
我们将来提供下载的Servlet可能只会写一个,总不能下载一堆图片就要写一堆的Servlet叭?太费时间了,所以我们通常只创建一个具有下载功能的Servlet,那么问题来了,如果只有一个具有下载功能的Servlet,那在前端点击超链接后全部跳转到同一个downloadServlet,那downloadServlet该如何分辨是哪个超链接,该下载哪张图片呢?
解决方法:
在href属性值后面在加一个属性:资源名称fileame=xxx,就可以通过传递这个资源名称filename来分辨是哪张图片的超链接!
2、编写downloadServlet
@WebServlet("/downloadServlet")
public class downloadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*1 获取请求参数:filename 文件的名称*/
String filename = request.getParameter("filename"); /**注意:filename = 小黄人图片.jpg,而不等于 /小黄人图片.jpg ,没有一条斜杠!!*/
/*2 使用字节输入流加载文件进内存*/
//2.1 找到图片的服务器路径
ServletContext servletContext = request.getServletContext();
String realPath = servletContext.getRealPath("/img/" + filename);/**点睛之笔*/
//2.2 用字节输入流关联图片的服务器路径,使图片加载进内存
FileInputStream inputStream = new FileInputStream(realPath);
/*3 设置response响应头*/
//3.1 设置响应头:content-type 需要用到文件的MIME类型
// 获取图片文件的MIME类型,参数是带后缀名的文件名称
String mimeType = servletContext.getMimeType(filename);
response.setContentType(mimeType);
//3.2 设置响应头:content-disposition
/**解决文件下载时弹框显示的文件中文名称乱码问题*/
/**1 获取user-agent请求头*/
String agent = request.getHeader("user-agent");
/**使用工具类方法编码文件名即可*/
filename = DownLoadUtils.getFileName(agent, filename);
// 参数"attachment;filename=小黄人图片.jpg"的意思如下:
// attachment 是响应给浏览器,让其以附件的形式打开响应体内容
// filename=小黄人图片.jpg 是展示给我们看的附件的名称
response.setHeader("content-disposition", "attachment;filename="+filename);
/*4 将输入流的数据用文件对拷的方式写出到输出流中*/
//4.1 创建字节输出流对象
ServletOutputStream outputStream = response.getOutputStream();
//4.2 文件对拷操作
byte[] buff = new byte[1024 * 8];
int len = 0;
while ((len = inputStream.read(buff)) != -1) {
outputStream.write(buff,0,len);
}
//4.3 因为输出流是response创建的,响应结束输出流就会自动关闭
// 而输入流却不会自动关闭,所以要手动关闭一下
inputStream.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}