黑马程序员技术交流社区

标题: 笔记 [打印本页]

作者: hy03030816    时间: 2019-8-30 16:15
标题: 笔记
文件下载的本质

        通过输出流将服务器上磁盘上的一个文件拷贝(写)到客户端磁盘上


servlet下载文件步骤
        1.将文件名称转换成为utf-8
        2.将文件转换成流
        3.处理不同浏览器中文乱码
                火狐浏览器要求中文文件名以Base64编码,其它浏览器一般以URLEncoder编码,所以需要根据浏览器类型分别处理
        4.设置下载时候的响应头(Content-Type和Content-Disposition)
                注意:如果content-type是通过后缀名获取的话,个别谷歌浏览器版本可能会直接打开文本或者图片,而不是下载的形式
        5.通过输出流将文件回写到浏览器完成下载.




通过servlet实现文件下载

download.html

        <!DOCTYPE html>
        <html>
        <head>
        <meta charset="UTF-8">
        <title>Insert title here</title>
        </head>
        <body>
        <h1>文件下载的列表页面</h1>
        <h3>手动编码方式下载</h3>
        <a href="/DownloadDemo_Servlet/down?filename=test.txt">test.txt</a><br/>
        <a href="/DownloadDemo_Servlet/down?filename=girl.jpg">girl.jpg</a><br/>
        <a href="/DownloadDemo_Servlet/down?filename=hello.zip">hello.zip</a><br/>
        <a href="/DownloadDemo_Servlet/down?filename=美女.jpg">美女.jpg</a><br/>
        </body>
        </html>


下载中文名称文件

        IE浏览器下载中文文件的时候采用的URL的编码.
        Firefox浏览器下载中文文件的时候采用的是Base64的编码.


        /**
         *将文件名称进行base64转换
         */
        public String base64EncodeFileName(String fileName) {
                BASE64Encoder base64Encoder = new BASE64Encoder();
                try {
                        return "=?UTF-8?B?"
                                        + new String(base64Encoder.encode(fileName
                                                        .getBytes("UTF-8"))) + "?=";
                } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                        throw new RuntimeException(e);
                }
        }

       
       
实例代码

public class DownloadServlet extends HttpServlet {
        private static final long serialVersionUID = -8967294054290769951L;

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                //------1.获取要下载的文件名称(需要处理如果参数为中文的情况)--------
                String filename = req.getParameter("filename");
                //------------------------------------------------------------------
               
                //------2.将该文件获取到并转换成输入流------------------------------
                String fileAbsPath = getServletContext().getRealPath("/download/"+filename);
                InputStream is = new FileInputStream(fileAbsPath);
                //------------------------------------------------------------------
               
                //注意:提前获取mimeType,不然文件名经过编码后再获取就会出问题
                String mimeType = getServletContext().getMimeType(filename);

                //------3.将文件名称处理成为被浏览器解析的名称----------------------
                String userAgent = req.getHeader("User-Agent");
                if(userAgent.contains("FireFox")) {
                        filename = base64EncodeFileName(filename);
                }else {
                        filename = URLEncoder.encode(filename, "utf-8");
                }
                //------------------------------------------------------------------
               
                //------4.设置响应头 content-type-----------------------------------
                resp.setHeader("Content-Type", mimeType);
                resp.setHeader("Content-Disposition", "attachment;filename="+filename);
                //------------------------------------------------------------------
               
                //------5.通过输出流将文件回写到浏览器完成下载----------------------
                OutputStream os = resp.getOutputStream();
                int len = 0;
                byte[] b = new byte[1024];
                while((len = is.read(b))!= -1){
                        os.write(b, 0, len);
                }
                is.close();
                //------------------------------------------------------------------
        }

        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                doGet(req, resp);
        }
       
       
        public String base64EncodeFileName(String fileName) {
                BASE64Encoder base64Encoder = new BASE64Encoder();
                try {
                        return "=?UTF-8?B?" + new String(base64Encoder.encode(fileName.getBytes("UTF-8"))) + "?=";
                } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                        throw new RuntimeException(e);
                }
        }

}


解决谷歌个别版本下载文本文件和图片直接打开的办法

将Content-Type的头的值写成application/x-msdownload即可

       
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                //------1.获取要下载的文件名称(需要处理如果参数为中文的情况)--------
                String filename = new String(req.getParameter("filename").getBytes("ISO-8859-1"),"utf-8");
                //------------------------------------------------------------------
               
                //------2.将该文件获取到并转换成输入流------------------------------
                String fileAbsPath = getServletContext().getRealPath("/download/"+filename);
                InputStream is = new FileInputStream(fileAbsPath);
                //------------------------------------------------------------------

                //------3.将文件名称处理成为被浏览器解析的名称----------------------
                String userAgent = req.getHeader("User-Agent");
                if(userAgent.contains("FireFox")) {
                        filename = base64EncodeFileName(filename);
                }else {
                        filename = URLEncoder.encode(filename, "utf-8");
                }
                //------------------------------------------------------------------
               
                //------4.设置响应头 content-type-----------------------------------
                resp.setHeader("Content-Type", "application/x-msdownload;");
                resp.setHeader("Content-Disposition", "attachment;filename="+filename);
                //------------------------------------------------------------------
               
                //------5.通过输出流将文件回写到浏览器完成下载----------------------
                OutputStream os = resp.getOutputStream();
                int len = 0;
                byte[] b = new byte[1024];
                while((len = is.read(b))!= -1){
                        os.write(b, 0, len);
                }
                is.close();
                //------------------------------------------------------------------
        }







欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2