1. 程式人生 > >Java Web實現檔案打包下載並解決亂碼問題

Java Web實現檔案打包下載並解決亂碼問題

Java Web實現檔案打包下載詳見程式碼:

作為工具類我封裝在FileUtil裡,解決壓縮亂碼要下載

apache-ant-zip.jar包

JDK中自帶的ZipOutputStream在壓縮檔案時,如果檔名中有中文,則壓縮後的

zip檔案開啟時發現中文檔名變成亂碼.

解決的方法是使用apache-ant-zip.jar包(見附件)中的ZipOutputStream和ZipEntry.

即,匯入類:

import org.apache.tools.zip.ZipEntry; 

import org.apache.tools.zip.ZipOutputStream;

並且注意,壓縮之前呼叫 ZipOutputStream的out.setEncoding(System.getProperty("sun.jnu.encoding")); 方法,

系統引數sun.jnu.encoding表示獲取當前系統中的檔名的編碼方式.這裡將ZipOutputStream的檔名編碼方式

設定成系統的檔名編碼方式.

解壓時,直接使用JDK原來的ZipInputStream即可.

但是有個 需要注意 的地方是,在讀取ZIP檔案之前,需要設定:

System.setProperty("sun.zip.encoding", System.getProperty("sun.jnu.encoding"));

將系統的ZIP編碼格式設定為系統檔名編碼方式,否則解壓時報異常.

(網上,還有修改ZipInputStream原始碼的方式貌似太麻煩了,參考:http://zwllxs.iteye.com/blog/871260)


 /**
     * 檔案打包下載
     *
     * @param tempFilePath 待建立臨時壓縮檔案
     * @param files        待壓縮檔案集合
     * @param request      請求
     * @param response     響應
     * @return response
     * @throws Exception 異常
     */

    public static HttpServletResponse downLoadZipFiles(String tempFilePath, List<File> files, HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            /**這個集合就是你想要打包的所有檔案,
             * 這裡假設已經準備好了所要打包的檔案*/


            //List<File> files = new ArrayList<File>();


            /**建立一個臨時壓縮檔案,
             * 我們會把檔案流全部注入到這個檔案中
             * 這裡的檔案你可以自定義是.rar還是.zip*/

            File file = new File(tempFilePath);
            if (!file.exists()) {
                file.createNewFile();
            }
            response.reset();


            //response.getWriter()
            //建立檔案輸出流
            FileOutputStream fous = new FileOutputStream(file);
            /**打包的方法我們會用到ZipOutputStream這樣一個輸出流,
             * 所以這裡我們把輸出流轉換一下*/

            ZipOutputStream zipOut = new ZipOutputStream(fous);
            zipOut.setEncoding(System.getProperty("sun.jnu.encoding"));//設定檔名編碼方式
            /**這個方法接受的就是一個所要打包檔案的集合,
             * 還有一個ZipOutputStream*/

            zipFile(files, zipOut);
            zipOut.close();
            fous.close();
            return downloadZip(file, response, request);
        } catch (Exception e) {
            e.printStackTrace();
        }
        /**直到檔案的打包已經成功了,
         * 檔案的打包過程被我封裝在FileUtil.zipFile這個靜態方法中,
         * 稍後會呈現出來,接下來的就是往客戶端寫資料了*/


        return response;
    }


    /**
     * 把接受的全部檔案打成壓縮包
     *
     * @param files
     * @param outputStream org.apache.tools.zip.ZipOutputStream
     */

    public static void zipFile(List files, ZipOutputStream outputStream) {
        int size = files.size();
        for (int i = 0; i < size; i++) {
            File file = (File) files.get(i);
            zipFile(file, outputStream);
        }
    }


    public static HttpServletResponse downloadZip(File file, HttpServletResponse response, HttpServletRequest request) {
        try {
            // 以流的形式下載檔案。
            InputStream fis = new BufferedInputStream(new FileInputStream(file.getPath()));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();


            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/x-msdownload");


            //如果輸出的是中文名的檔案,解決亂碼
            response.setHeader("Content-Disposition", "attachment;filename=\"" + new String(file.getName().getBytes("gbk"), "iso-8859-1") + "\"");
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                File f = new File(file.getPath());
                f.delete();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return response;
    }


    /**
     * 根據輸入的檔案與輸出流對檔案進行打包
     *
     * @param inputFile   File
     * @param ouputStream org.apache.tools.zip.ZipOutputStream
     */

    public static void zipFile(File inputFile, ZipOutputStream ouputStream) {
        try {
            if (inputFile.exists()) {
                /**如果是目錄的話這裡是不採取操作的,
                 * 至於目錄的打包正在研究中*/

                if (inputFile.isFile()) {
                    FileInputStream IN = new FileInputStream(inputFile);
                    BufferedInputStream bins = new BufferedInputStream(IN, 512);
                    //org.apache.tools.zip.ZipEntry
                    ZipEntry entry = new ZipEntry(inputFile.getName());
//                    ZipEntry entry = new ZipEntry(new String(inputFile.getName().getBytes(), "utf-8"));
                    ouputStream.putNextEntry(entry);
                    // 向壓縮檔案中輸出資料
                    int nNumber;
                    byte[] buffer = new byte[512];
                    while ((nNumber = bins.read(buffer)) != -1) {
                        ouputStream.write(buffer, 0, nNumber);
                    }
                    // 關閉建立的流物件
                    bins.close();
                    IN.close();
                } else {
                    try {
                        File[] files = inputFile.listFiles();
                        for (int i = 0; i < files.length; i++) {
                            zipFile(files[i], ouputStream);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

 Controller層呼叫:

  @ActionAnnotation(name = "生成函調報告1,2文件並下載", group = "查詢")
    public ModelAndView createWord1(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Management management = managementService.query(request.getParameter("mm_id"));
        Map<String, Object> model = new HashMap<String, Object>();
        model.put("management", management);
        String view = SystemParameter.get("soldier");
        Template template = freeMarkerConfigurer.getConfiguration().getTemplate(SystemParameter.get("tempDirSoldier") + "/soldier.ftl", "utf-8");
        String temp = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
        File file = new File(getServletContext().getRealPath(view));
        FileUtils.writeStringToFile(file, temp, "utf-8");
        String view1 = SystemParameter.get("unSoldierly");
        Template template1 = freeMarkerConfigurer.getConfiguration().getTemplate(SystemParameter.get("tempDirSoldier") + "/unSoldierly.ftl", "utf-8");
        String temp1 = FreeMarkerTemplateUtils.processTemplateIntoString(template1, model);
        File file1 = new File(getServletContext().getRealPath(view1));
        FileUtils.writeStringToFile(file1, temp1, "utf-8");
        List<File> fileList = new ArrayList<File>();
        fileList.add(file);
        fileList.add(file1);
        FileUtil.downLoadZipFiles(getServletContext().getRealPath(SystemParameter.get("tempDirZipReport")), fileList, request, response);
        return responseText(response, "1");
    }

效果如圖: