瀏覽器兼容性--IE11以及Edge等下載文件的中文名出現亂碼,前后端解決方案


項目中有用到文件下載功能,之前在處理下載時對IE瀏覽器下文件下載名進行過處理,測試也沒有問題,
但是功能上線后,業務反饋IE11文件下載文件名依然亂碼。打印User-Agent字符串如下:


IE11 User-Agent字符串:Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
IE6~IE10版本的User-Agent字符串:Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.0; Trident/6.0)

 

一、后端修改

IE瀏覽器在IE11,更改了User-Agent字符串格式內容,所以針對IE11,做一下判斷即可:(后端代碼更改)

//下載文件,並處理文件名亂碼
        public void downloadFile(HttpServletRequest request,HttpServletResponse response){
           String path = request.getSession().getServletContext().getRealPath("/upload/文檔1.doc");
            // path是根據日志路徑和文件名拼接出來的
             File file = new File(path);
            //獲取日志文件名稱
              String filename = file.getName();
           try {
              //判斷是否是IE11
              Boolean flag= request.getHeader("User-Agent").indexOf("like Gecko")>0;
             
               if (request.getHeader("User-Agent").toLowerCase().indexOf("msie") >0||flag){
                   filename = URLEncoder.encode(filename, "UTF-8");//IE瀏覽器
               }else {
                //先去掉文件名稱中的空格,然后轉換編碼格式為utf-8,保證不出現亂碼,
                //這個文件名稱用於瀏覽器的下載框中自動顯示的文件名
                filename = new String(filename.replaceAll(" ", "").getBytes("UTF-8"), "ISO8859-1");
                //firefox瀏覽器
                //firefox瀏覽器User-Agent字符串: 
                //Mozilla/5.0 (Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0
               }
            InputStream fis = new BufferedInputStream(new FileInputStream(path));
               byte[] buffer;
            buffer = new byte[fis.available()];
               fis.read(buffer);
               fis.close();
               response.reset();
               response.addHeader("Content-Disposition", "attachment;filename=" +filename);
               response.addHeader("Content-Length", "" + file.length());
               OutputStream os = response.getOutputStream();
               response.setContentType("application/octet-stream");
               os.write(buffer);// 輸出文件
               os.flush();
               os.close();
           } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
           }
          }

 

二、前端修改

同時作為前端也需要有一個兼容IE的心。

 只需要在中文前加上encodeURI函數,將其他部分字符串拼接。

 

encodeURI()是Javascript中真正用來對URL編碼的函數。

 

它着眼於對整個URL進行編碼,因此除了常見的符號以外,對其他一些在網址中有特殊含義的符號“; / ? : @ & = + $ , #”,也不進行編碼。編碼后,它輸出符號的utf-8形式,並且在每個字節前加上%。

 

 $scope.commonWord = baseUrl+"/downloadFile.htm?objectId="+encodeURI('歡迎你加入我們手冊')+".pdf&fileName="+encodeURI('歡迎你加入我們手冊')+".pdf";

 

本來在測試和預生產上都OK,發線上版本之后上突然發現IE11下的不同

 

我的這個IE11的版本出現這個問題--中文亂碼的問題。

 

 但是在其他版本的IE11居然可以正常下載。

 

我勒個去

 

IE居然還在不同的版本之間出現這個問題。你讓我怎么兼容。

 

自己又想了一下,還有可能是不同的win系統下的IE11也會出現不同。

 

最后后端的修改,完美的解決了這個問題;

之前的是

 //2.設置文件頭:最后一個參數是設置下載文件名(假如我們叫a.pdf)
            response.setHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes("utf-8"), "ISO8859-1"));

修改之后:

/**
     * 構建附件下載回執
     *
     * @param response - 回執
     * @param fullPath - 全路徑
     * @param fileName - 文件名(含后綴)
     * @throws Exception
     */
    private void createDownloadFileResponse(HttpServletResponse response, String fullPath, String fileName)
            throws IOException {
        ServletOutputStream out = null;
        FileInputStream in = null;
        File file = null;
        try {
            //1.設置文件ContentType類型,這樣設置,會自動判斷下載文件類型
            response.setContentType("multipart/form-data");

            //2.設置文件頭:最后一個參數是設置下載文件名(假如我們叫a.pdf)
            response.setHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes("gb2312"), "ISO8859-1")); // 通過文件路徑獲得File對象(假如此路徑中有一個download.pdf文件)
            file = new File(fullPath);

            in = new FileInputStream(file);

            // 3.通過response獲取ServletOutputStream對象(out)
            out = response.getOutputStream();

            int len = 0;
            byte[] buffer = new byte[1024];
            // 循環將輸入流中的內容讀取到緩沖區當中
            while ((len = in.read(buffer)) > 0) {
                // 輸出緩沖區的內容到瀏覽器,實現文件下載
                out.write(buffer, 0, len);
            }
        } catch (Exception e) {
            logger.error(new StringBuilder("CustomServiceController -> createDownloadFileResponse Error:"
                    + "構建附件下載回執出現異常,異常信息為:").append(e).toString());
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
                out.flush();
            }
            if (file != null && file.exists()) {
                file.delete();
            }
        }
    }

    /*
     * 判斷是否是ie瀏覽器如下
     */
    public static boolean isMSBrowser(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        for (String signal : IEBrowserSignals) {
            if (userAgent.contains(signal))
                return true;
        }
        return false;
    }

為什么會出現這種情況:

因為在前端頁面已經將中文字符,encodeURI編碼轉換成utf-8,但是在發送ajax異步請求的時候,IE瀏覽器總會采用GB2312編碼方式(操作系統默認的方式),所以在后端拿到字符串的時候是gb2312編碼之后的字符串,所以后端還是需要的是對gb2312編碼的字符串進行解碼,而不是對utf-8的字符進行解碼。

 

總結一下:

js中url編碼&傳的值給其他的頁面,多參數網址作為整體編碼后傳值。比如說是http://www.chengxinsong.cn?id=http://chengxinsong.cn/saucxs/?id1=1&id2=2,這個時候參數id所獲得的值並不是 http://ilcng.com/xmxy/?id1=1&id2=2而是http://ilcng.com/xmxy/?id1=1,也就是說從&符號的地方截斷了,因為&符號是特殊符號不能直接傳遞,需要經過編碼以后才能傳遞。

一般來說,URL只能使用英文字母、阿拉伯數字和某些標點符號,不能使用其他文字和符號。這是因為網絡標准RFC 1738做了硬性規定。

只有字母和數字[0-9a-zA-Z]、一些特殊符號“$-_.+!*'(),”[不包括雙引號]、以及某些保留字,才可以不經過編碼直接用於URL。

這意味着,如果URL中有漢字,就必須編碼后使用。

1、網址路徑的編碼,用的是utf-8編碼;

使用的是chrome瀏覽器

 

當我使用IE11的瀏覽器,查看HTTP請求的頭信息,會發現IE實際查詢的網址是“http://www.cnblogs.com/chengxs/%E7%A8%8B%E6%96%B0%E6%9D%BE”。也就是說,IE自動將“程新松”編碼成了“%E7%A8%8B%E6%96%B0%E6%9D%BE”。在每個字節前加上%而得到的。

我把chrome瀏覽器的url復制到IE上,就出現了如下圖所示的:

 

2、查詢字符串的編碼,用的是操作系統的默認編碼。

3、GET和POST方法的編碼,用的是網頁的編碼。

4、在Ajax調用中,IE總是采用GB2312編碼(操作系統的默認編碼),而Firefox總是采用utf-8編碼。

 

歡迎訪問:

1、雲商城isv系統http://isv.suningcloud.com/mpisv-web/index

 2、雲商城消費者門戶http://www.suningcloud.com/promotion/index/experience_center.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM