使用迭代器模式和組合模式實現瀏覽器一鍵導出下載為zip壓縮包文件
由于項目需要,于是又想起之前看過的設計模式,于是便有了一鍵導出的想法。
思路簡單明了。一步一步看下去就好。
1.創建組合對象
public abstract class FileComponent { /** * Description: 遞歸創建文件夾,或者文件 */ public void mkFile(){ throw new UnsupportedOperationException(); } /** * Description: 獲取文件輸入路徑 */ public String getInPath(){ throw new UnsupportedOperationException(); } /** * Description: 獲取文件輸出路徑 */ public String getOutPath(){ throw new UnsupportedOperationException(); } /** * Description: 對于文件夾來說是可以add其他文件夾或者文件 */ public void add(FileComponent fileComponent){ throw new UnsupportedOperationException(); }}
此組合對象,可以是文件夾對象,也可是具體的文件對象,再后面調用中,不需要了解到底是一個文件夾還是一個文件(即組合模式的透明性)。
2.組合對象抽象類的實現
上述抽象類的實現如下:
public class ZipFileItem extends FileComponent{ //輸入文件的路徑 String inPath; //輸出文件的路徑 String outPath; //子節點文件信息 List<FileComponent> fileComponents = new ArrayList<FileComponent>(); //inPath 可以為null public ZipFileItem(String outPath){ this.outPath =outPath; } //壓縮文件的源目錄路徑和壓縮好的目標位置 public ZipFileItem(String inPath,String outPath){ this.inPath =inPath; this.outPath =outPath; } public void add(FileComponent fileComponent){ fileComponents.add(fileComponent); } public void remove(FileComponent fileComponent){ fileComponents.remove(fileComponent); } @Override public String getInPath(){ return inPath; } @Override public String getOutPath(){ return outPath; } @Override public void mkFile(){ FileUtils.createFile(inPath, outPath); Iterator<FileComponent> iterator = fileComponents.iterator(); //如果是文件夾,那么還可以迭代文件及對象中的具體文件對象 while (iterator.hasNext()) { FileComponent fileComponent = iterator.next(); fileComponent.mkFile(); } }}
3.文件工具類
public class ConferenceFileUtils { /** * Description: 根據文件的絕對路徑,在絕對的輸出路徑進行創建文件 * @param inPath 輸入路徑,如果是要根據已有的文件來創建,那么一定要傳 * @param outPath 輸出路徑,如果是目錄則不用 */ public static void createFile(String inPath,String outPath){ File fileIn = new File(inPath); File fileOut = new File(outPath); //如果目標文件已存在,則忽略,如果文件不存在 。則進行創建 if (!fileOut.exists()) { int lastSeparator = outPath.lastIndexOf(File.separator); String lastPart = outPath.substring(lastSeparator); //如果不是文件夾,則創建文件 if (lastPart.lastIndexOf(".")!=-1) { LoggerUtil.info("----------making concreteFile--------"+outPath); FileInputStream in = null; FileOutputStream out = null; File directory = null; try { directory = new File(outPath.substring(0, lastSeparator+1)); directory.mkdirs(); out=new FileOutputStream(fileOut); //如果源文件存在 if (fileIn.exists()) { in=new FileInputStream(fileIn); int len; byte[] buf=new byte[10240]; while((len=in.read(buf))>0){ out.write(buf,0,len); } out.close(); in.close(); in = null; } } catch (IOException e) { System.err.println("creating file failed!", e); } } //如果是文件夾則創建文件夾,如果父類文件夾不存在,那么也創建 else { System.err.println("----------making directory--------"+outPath); fileOut.mkdirs(); } } } //遞歸刪除文件夾以及文件 public static boolean deleteDir(File dir) { if (dir.isDirectory()) { String[] children = dir.list(); //遞歸刪除目錄中的子目錄 for (int i=0; i<children.length; i++) { boolean success = deleteDir(new File(dir, children[i])); if (!success) { return false; } } } // 目錄此時為空,可以刪除 return dir.delete(); } // 輸出文件對象到輸出流 public static void outputFile(File file, HttpServletResponse response) throws IOException { OutputStream out=null; FileInputStream in=null; try { byte[] src = new byte[1024]; out = response.getOutputStream(); in = new FileInputStream(file); int len=0; while ((len = in.read(src)) > 0) { out.write(src, 0, len); } out.flush(); out.close(); in.close(); } catch (IOException e) { throw new IOException(e); }finally{ if(null!=out){ FortifyUtil.commonReleasedResource(out); } if(null!=in){ FortifyUtil.commonReleasedResource(in); } } }}
4.核心導出邏輯代碼
public class exportMaterialToZipTemplate { @Resource private EnrichFileLevelsService enrichFileLevelsService; //根目錄文件夾名稱 or 下載瀏覽器文件名 private String downloadZipName; //根目錄地址 private String savePath = "d://tempFile"; //根目錄路徑 private String superRootPath; //根目錄對象 private FileComponent superRoot; //業務參數DTO private ExportAllTheMaterialDTO paramDTO; //response private HttpServletResponse response; public exportMaterialToZipTemplate(ExportAllTheMaterialDTO paramDTO,EnrichFileLevelsService enrichFileLevelsService,HttpServletResponse response) { this.downloadZipName = paramDTO.getDownloadZipName(); this.paramDTO = paramDTO; this.response = response; this.enrichFileLevelsService = enrichFileLevelsService; this.superRootPath =savePath+File.separator+downloadZipName; this.superRoot = new ZipFileItem(superRootPath); } //1.封裝根目錄 private void enrichFileLevels(){ enrichFileLevelsService.enrichFileLevels(superRoot,superRootPath,paramDTO); } //2.生成文件目錄層級,即創建所有的文件(包括文件夾) private void createAllTheFiles(){ if (null!=superRoot) { superRoot.mkFile(); } } //3.生成文件層級后后再壓縮后下載到瀏覽器 private void compressAndDownload() { File srcFile = new File(FortifyUtil.filterFileName(superRootPath)); String targetFilePath = savePath+File.separator+srcFile.getName()+".zip"; File targetFile = new File(FortifyUtil.filterFileName(targetFilePath)); ZipFileUtil.zipFiles(srcFile,targetFile); try { //壓縮文件臨時路徑 String downFileName = downloadZipName+".zip"; response.reset(); // 定義輸出類型 response.setContentType("application/octet-stream"); response.setHeader("content-disposition", "attachment;filename=" + new String(downFileName.getBytes("GBK"), "ISO-8859-1") + ";size=" + targetFile.length()); OutputFileUtil.outputFile(targetFile, response); // 刪除臨時存放的文件夾 if (srcFile.exists()) { ConferenceFileUtils.deleteDir(srcFile); } //刪除臨時的壓縮包 if (targetFile.exists()) { targetFile.delete(); } } catch (IOException e) { DevLog.error(e.getMessage()); } } //一鍵導出,外觀模式 public void export() { enrichFileLevels(); createAllTheFiles(); compressAndDownload(); }}
5.豐富文件層級的接口
public interface EnrichFileLevelsService { public void enrichFileLevels(FileComponent superRoot,String superRootPath,ExportAllTheMaterialDTO paramDTO);}
不同的業務場景只要實現這接口,實現enrichFileLevels()方法,將實現此接口的
類實例傳到exportMaterialToZipTemplate類的構造方法,然后調用exportMaterialToZipTemplate類實例的export()方法即可。即
new exportMaterialToZipTemplate(dtoParams,
enrichFileLevelsService, response).export();
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。
新聞熱點
疑難解答
圖片精選