一、文件下载案例需求
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);}}
