1. 程式人生 > >批量檔案打包下載

批量檔案打包下載

最近工作上有個需求,獲取批量檔案,打包下載,如果原始檔名中有重複,則需要重新命名(加角標),如果壓縮後文件超過20兆,出於寬頻考慮,不下載,但給與提示.

思路. 先獲取所有檔案,重新命名,再壓縮存起來再判斷大小,滿足大小寫出流,不滿足給與提示

話不多說,如下程式碼可以直接執行

package com.fisher.cloud.controller;

import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody;

/**  * @author Fisher  */ @Controller @RequestMapping("/test") public class Test {

    private static final Logger logger = LoggerFactory.getLogger(Test.class);

    /**      * 獲取目錄下面所有檔案並打包,壓縮成一個hello.zip包,如果被壓縮原始檔名字有重複,在增加下標,如果壓縮包大於20兆,出於對寬頻的考慮就不下載      * ,但給與提示.      */     @RequestMapping(value = "/download", method = RequestMethod.GET)     @ResponseBody     public String downloadAttachment(HttpServletResponse response) throws IOException {         //測試如下2個目錄下的檔案打包,兩個目錄一樣的是為了測試重新命名問題         File file1 = new File("D:\\IT\\參考資料\\檔案匯入匯出");         File file2 = new File("D:\\IT\\參考資料\\檔案匯入匯出");         File file3 = new File("D:\\IT\\參考資料\\檔案下載模板匯出方式");

        // 獲取所有檔案         List<File> fileList1 = Arrays.asList(file1.listFiles());         List<File> fileList2 = Arrays.asList(file2.listFiles());         List<File> fileList3 = Arrays.asList(file3.listFiles());         List<File> totalFile = new ArrayList<>();         if (fileList1.size() > 0) {             for (File f : fileList1) {                 totalFile.add(f);             }         }         if (fileList2.size() > 0) {             for (File f : fileList2) {                 totalFile.add(f);             }         }         if (fileList3.size() > 0) {             for (File f : fileList3) {                 totalFile.add(f);             }         }         try {             // 壓縮檔案 到"D:\IT\test",名字為 "hello.zip             File zipFile = this.zipFiles(totalFile, "D:\\IT\\test", "hello.zip");             // 如果壓縮檔案大於20兆,返回提示             Integer maxSize = 20;             if (maxSize * 1024 * 1024 < zipFile.length()) {                 return "壓縮包超過規定的20兆大小,限制下載";             } else {                 // 將檔案寫出                 writeOut(response, zipFile);             }         } catch (Exception e) {             e.printStackTrace();         }         return null;

    }

    // 批量檔案壓縮成zip包     public File zipFiles(List<File> fileList, String zipPath, String zipName) throws IOException {         // 如果被壓縮檔案中有重複,會重新命名         Map<String, String> namePathMap = getTransferName(fileList);         File zipPathFile = new File(zipPath);         // 資料夾不存在則建立         if (!zipPathFile.exists()) {             zipPathFile.mkdirs();         }         File zipFile = new File(zipPath + File.separator + zipName);         if (!zipFile.exists()) {             zipFile.createNewFile();         }         ZipOutputStream zos = null;         BufferedInputStream bis = null;         try {             // 存放的目標檔案             zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile.getPath())));             Set<String> keySet = namePathMap.keySet();             ZipEntry zipEntry = null;             for (String key : keySet) { // key是檔名,value是path                 // 指定原始檔                 File sourceFile = new File(namePathMap.get(key));                 // 建立ZIP實體,並新增進壓縮包,指定壓縮檔案中的檔名                 zipEntry = new ZipEntry(key);                 zos.putNextEntry(zipEntry);                 // 讀取待壓縮的檔案並寫進壓縮包裡                 bis = new BufferedInputStream(new BufferedInputStream(new FileInputStream(sourceFile), 1024 * 10));                 byte[] bufs = new byte[1024 * 10];                 int read = 0;                 while ((read = (bis.read(bufs, 0, 1024 * 10))) != -1) {                     zos.write(bufs, 0, read);                 }                 if (bis != null) {                     bis.close();                 }             }

        } catch (Exception e) {             e.printStackTrace();         } finally {             // 關閉流             if (bis != null) {                 bis.close();             }             if (null != zos) {                 zos.close();             }         }         return zipFile;

    }

    /**      * 將檔案寫出到流 【方法名】{方法的功能/動作描述}      * @author Fisher      *       * */     private void writeOut(HttpServletResponse response, File zipFile) throws IOException {         response.reset();         response.setContentType("application/zip");         response.setCharacterEncoding("utf-8");         response.setHeader("Content-Disposition", "attachment;filename=" + zipFile.getName());         OutputStream outputStream = response.getOutputStream();         FileInputStream fis = null;         try {             fis = new FileInputStream(zipFile.getPath());             int len = 0;             byte[] buffer = new byte[1024];             while ((len = fis.read(buffer)) > 0) {                 outputStream.write(buffer, 0, len);             }             outputStream.flush();         } finally {             if (null != fis) {                 fis.close();             }             if (null != outputStream) {                 outputStream.close();             }         }     }

    // 計算壓縮包如果已存在重複的名稱,則在重複檔案後面跟上數字 如: 檔案(1).doc,檔案(2).doc     public Map<String, String> getTransferName(List<File> fileList) {         if (fileList == null || fileList.size() == 0) {             return new HashMap<String, String>();         }         // key存放檔名,value存放path         Map<String, String> fileNameMap = new HashMap<>();         List<String> fileNames = new ArrayList<>();         for (File file : fileList) {             // 獲取檔名             String fileName = file.getName();             int count = 0;

            for (String name : fileNames) {                 if (name != null && name.equals(fileName)) {                     count++;                 }             }             fileNames.add(fileName);             if (count > 0) {                 int lastIndex = fileName.lastIndexOf('.');                 String name = fileName.substring(0, lastIndex);                 String type = fileName.substring(lastIndex + 1, fileName.length());                 fileName = new StringBuilder().append(name).append("(").append(count).append(")").append(".")                         .append(type).toString();                 fileNameMap.put(fileName, file.getPath());             } else {                 fileNameMap.put(fileName, file.getPath());             }         }         return fileNameMap;     }

}  

測試結果:相同名字會重複命名

超過20兆不下載,給與提示