一、文件下载案例需求

1、页面显示超链接
2、点击超链接后弹出下载提示框
3、完成图片文件下载


二、注意

如果超链接的href属性直接写为工作空间里的图片路径,点击超链接后,浏览器是不会弹出下载提示框的,因为浏览器会默认解析图片然后进行展示!
而如果是像视频之类的,浏览器就默认不解析视频,会给你弹出一个下载提示!

也就是说,如果超链接指向的资源可以被浏览器解析,则在浏览器中直接展示,如果不能被浏览器直接解析,就会弹出下载提示框!

所以!要弹出下载提示框下载图片的操作就比较麻烦一点!


三、分析

使用响应头设置资源的打开方式:
content-disposition:attachment;filename=xxx
注意:xxx是将来下载提示框里展示的文件的名称

四、步骤

1、编写前端页面

编辑超链接的href属性值,使其指向downloadServlet!
但要注意:
我们将来提供下载的Servlet可能只会写一个,总不能下载一堆图片就要写一堆的Servlet叭?太费时间了,所以我们通常只创建一个具有下载功能的Servlet,那么问题来了,如果只有一个具有下载功能的Servlet,那在前端点击超链接后全部跳转到同一个downloadServlet,那downloadServlet该如何分辨是哪个超链接,该下载哪张图片呢?
解决方法:
在href属性值后面在加一个属性:资源名称fileame=xxx,就可以通过传递这个资源名称filename来分辨是哪张图片的超链接!
QQ图片20200710215630.png


2、编写downloadServlet

  1. @WebServlet("/downloadServlet")
  2. public class downloadServlet extends HttpServlet {
  3. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  4. /*1 获取请求参数:filename 文件的名称*/
  5. String filename = request.getParameter("filename"); /**注意:filename = 小黄人图片.jpg,而不等于 /小黄人图片.jpg ,没有一条斜杠!!*/
  6. /*2 使用字节输入流加载文件进内存*/
  7. //2.1 找到图片的服务器路径
  8. ServletContext servletContext = request.getServletContext();
  9. String realPath = servletContext.getRealPath("/img/" + filename);/**点睛之笔*/
  10. //2.2 用字节输入流关联图片的服务器路径,使图片加载进内存
  11. FileInputStream inputStream = new FileInputStream(realPath);
  12. /*3 设置response响应头*/
  13. //3.1 设置响应头:content-type 需要用到文件的MIME类型
  14. // 获取图片文件的MIME类型,参数是带后缀名的文件名称
  15. String mimeType = servletContext.getMimeType(filename);
  16. response.setContentType(mimeType);
  17. //3.2 设置响应头:content-disposition
  18. /**解决文件下载时弹框显示的文件中文名称乱码问题*/
  19. /**1 获取user-agent请求头*/
  20. String agent = request.getHeader("user-agent");
  21. /**使用工具类方法编码文件名即可*/
  22. filename = DownLoadUtils.getFileName(agent, filename);
  23. // 参数"attachment;filename=小黄人图片.jpg"的意思如下:
  24. // attachment 是响应给浏览器,让其以附件的形式打开响应体内容
  25. // filename=小黄人图片.jpg 是展示给我们看的附件的名称
  26. response.setHeader("content-disposition", "attachment;filename="+filename);
  27. /*4 将输入流的数据用文件对拷的方式写出到输出流中*/
  28. //4.1 创建字节输出流对象
  29. ServletOutputStream outputStream = response.getOutputStream();
  30. //4.2 文件对拷操作
  31. byte[] buff = new byte[1024 * 8];
  32. int len = 0;
  33. while ((len = inputStream.read(buff)) != -1) {
  34. outputStream.write(buff,0,len);
  35. }
  36. //4.3 因为输出流是response创建的,响应结束输出流就会自动关闭
  37. // 而输入流却不会自动关闭,所以要手动关闭一下
  38. inputStream.close();
  39. }
  40. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  41. this.doPost(request, response);
  42. }
  43. }