文件下载时直接对流进行zip加密压缩

下载文件时直接对流进行zip加密压缩

1、使用form提交表单,请求下载.do

2、使用zip4j_1.3.1.jar

<span style="white-space:pre">	</span>/**
	 * 下载对账账单明细文件
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView downloadCheckBill(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		
		try {
			EntCurrentUser entCurrentUser = new EntCurrentUser(request);
			EntUser entUser = entCurrentUser.getEntCurrentUser();
			
			String batchNo = request.getParameter("batchNo_form");
			String filePath = request.getParameter("filePath_form");
			String pwd = request.getParameter("pwd_form");
			
			String filePathRoot = PropertiesUtil.getResourceString("cloud.checkbill_file_path");
			String filePathAll = filePathRoot + filePath;
			
			Map<String,Object> paramMap = new HashMap<String,Object>();
			paramMap.put("userName", entUser.getUserName());
			paramMap.put("batchNo", batchNo);
			paramMap.put("filePath", filePath);
			logger.info("ajax下载-对账账单明细文件,请求参数:paramMap=" + paramMap);
			
			String fileName =  filePathAll.substring(filePathAll.lastIndexOf("/")+1);
			String zipFileName = fileName+".zip";
			
			//获取输出到页面的流
			response.setContentType("application/x-msdownload;charset=utf-8");
			response.addHeader("Content-Disposition", "attachment;filename=" + zipFileName);
			response.setBufferSize(81920);
			OutputStream os = response.getOutputStream();
			
			//将nas文件读取到流中
			FileInputStream fis = new FileInputStream(filePathAll);
			ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
			byte[] b = new byte[1024];
			int n;
			int off = 0;
			while ((n = fis.read(b)) != -1) {
				bos2.write(b, off, n);
			}
			fis.close();			
			
			ZipOutputStream outputStream = new ZipOutputStream(os,new ZipModel());
			ZipParameters parameters = new ZipParameters();
			parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
			parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
			parameters.setSourceExternalStream(true);
			parameters.setFileNameInZip(fileName);
			parameters.setEncryptFiles(true);
			parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD);
			parameters.setPassword(pwd);
			
			outputStream.putNextEntry(null, parameters);
			outputStream.write(bos2.toByteArray());
			
			bos2.flush();
			bos2.close();
			
			outputStream.flush();
			outputStream.closeEntry();
			outputStream.finish();
			outputStream.close();
			
			os.flush();
			logger.info("ajax下载-对账账单明细文件成功");
		} catch (Exception e){
			logger.info("下载过程失败出现异常",e);
		}
		return null;
	}

1、参考文章1内容

JQuery的ajax函数的返回类型只有xml、text、json、html等类型,没有“流”类型,所以我们要实现ajax下载,不能够使用相应的ajax函数进行文件下载。但可以用js生成一个form,用这个form提交参数,并返回“流”类型的数据。在实现过程中,页面也没有进行刷新。

var form=$("<form>");//定义一个form表单
form.attr("style","display:none");
form.attr("target","");
form.attr("method","post");
form.attr("action","exportData");
var input1=$("<input>");
input1.attr("type","hidden");
input1.attr("name","exportData");
input1.attr("value",(new Date()).getMilliseconds());
$("body").append(form);//将表单放置在web中
form.append(input1);

form.submit();//表单提交 

2、参考文章2内容

最近公司准备让各项目组提供公共工具组件,手中正好无事便研究其中一个工具 - 文件压缩与解压缩工具。

          目前JAVA API已提供对于ZIP文件的压缩与解压缩,但网上总结不支持ZIP文件加密与解密甚至对于中文支持也有问题,于是果断找其他的支持加密解密的第三方包。 winzipaes 与 ZIP4J 都符合项目的要求 ,最终选择ZIP4J来进行使用。

  • ZIP4J 是一个支持处理ZIP文件的开源库
  • 支持创建,修改,添加,删除,解压 压缩文件
  • 支持读/写密码保护
  • 支持AES加密 128/256
  • 支持标准ZIP加密
  • 支持进度监视器
  • 自持Unicode 文件名
  • 支持创建分卷压缩文件
  • 支持将文件添加到压缩包中但不进行压缩

ZIP4J 项目地址为  :http://www.lingala.net/zip4j/ ,但该地址无法直接访问需要使用代理进行访问

再提供一个在线代理网站:http://www.7daili.com/

目前ZIP4J 版本为:1.3.1 ,只需要直接下一载一个zip4j_1.3.1.jar一个jar包即可,同时可以下载官网提供的例子进行学习,例子相当详细(官网提供的例子的jdk 为1.4的版本 导入后需要修改一下)

官网提供的例子程序比较简单与小巧 整个程序也就一百多k,但demo程序对于各种功能的使用讲的非常详细。

项目包结构分为三层:

  • ZIP:该包下主要讲述压缩包的新增,修改,删除等例子(包含加密文件创建,通过流的方式创建 、添加压缩文件 、创建分卷压缩文件);
  • MISC:该包下主要展示几个工具方法例子,如:是否是分卷压缩包的判断、获取压缩包中的文件信息(文件名 大小等信息)、压缩进度查看、根据文件名删除压缩包对应文件等;
  • EXTRACT:该包下例子都是关于解压压缩包的例子,包括解压加密文件等;

示例代码

示例代码中需要对文件进行操作,为方便程序运行创建以下三个文件 可以直接运行大多数代码

  1. sample.txt
  2. myvideo.avi
  3. mysong.mp3

示例1 创建压缩包添 加文件到压缩包中(未设置加密)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public  class  AddFilesDeflateComp {
      
     public  AddFilesDeflateComp() {
         try  {
              
             ZipFile zipFile =  new  ZipFile( "c:\\ZipTest\\AddFilesDeflateComp.zip" );
              
             ArrayList<File> filesToAdd =  new  ArrayList<File>();
             filesToAdd.add( new  File( "c:\\ZipTest\\sample.txt" ));
             filesToAdd.add( new  File( "c:\\ZipTest\\myvideo.avi" ));
             filesToAdd.add( new  File( "c:\\ZipTest\\mysong.mp3" ));
              
             ZipParameters parameters =  new  ZipParameters();
             parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);  // set compression method to deflate compression              parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); 
             zipFile.addFiles(filesToAdd, parameters);
              
         catch  (ZipException e) {
             e.printStackTrace();
         }   
     }
      
     /**
      * @param args
      */
     public  static  void  main(String[] args) {
         new  AddFilesDeflateComp();
     }
  
}
  • 该类主要用于创建普通压缩包。如果压缩包不存在 则会自动创建一个ZIP包;如果已经存在一个不为空的同名ZIP压缩包 会将内容添加到该同名压缩包中。
  • 如果手动创建一个格式为ZIP的空压缩包进行保存,则为抛出异常:ZipException :Negative seek offset
  • 如果将其他的文件后缀修改为ZIP包再运行程序,也会抛出异常:ZipException: zip headers not found. probably not a zip file
  • ZIP4J 提供ZipParameters对象来进行压缩参数设置,其中setCompressionMethod方法可以设置压缩还是 不压缩

示例2 创建压缩包添加文件到 指定目录中进行压缩

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public  class  AddFilesToFolderInZip {
  
     public  AddFilesToFolderInZip() {
         try  {
             ZipFile zipFile =  new  ZipFile( "c:\\ZipTest\\AddFilesDeflateComp.zip" );
             ArrayList<File> filesToAdd =  new  ArrayList<File>();
             filesToAdd.add( new  File( "c:\\ZipTest\\sample.txt" ));
             filesToAdd.add( new  File( "c:\\ZipTest\\myvideo.avi" ));
             filesToAdd.add( new  File( "c:\\ZipTest\\mysong.mp3" ));
              
             ZipParameters parameters =  new  ZipParameters();
             parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
              
             parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
             parameters.setRootFolderInZip( "test2/" );
              
  
             zipFile.addFiles(filesToAdd, parameters);
         catch  (ZipException e) {
             e.printStackTrace();
        
          
          
     }
      
     /**
      * @param args
      */
     public  static  void  main(String[] args) {
         new  AddFilesToFolderInZip();
     }
  
}

  • 该程序执行后,会将sample.txt、myvideo.avi、mysong.mp3 添加到test2文件夹中 并生成AddFilesDeflateComp.zip 压缩包
  • 如果已经存在AddFilesDeflateComp.zip,则会将需要打包的内容添加到已经存在的压缩包去

示例3 添加文件夹到压缩包中

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public  class  AddFolder {
      
     public  AddFolder() {
          
         try  {
              
             ZipFile zipFile =  new  ZipFile( "c:\\ZipTest\\AddFolder.zip" );
             String folderToAdd =  "c:\\FolderToAdd" ;
          
             ZipParameters parameters =  new  ZipParameters();
              
             parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
             parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
             zipFile.addFolder(folderToAdd, parameters);
              
         catch  (ZipException e) {
             e.printStackTrace();
         }
     }
      
     public  static  void  main(String[] args) {
         new  AddFolder();
     }
      
}
  • 需要添加的文件夹必须存在,否则抛出异常:ZipException: input folder does not exist
  • * 如果已经存在同名文件则会出现一个文件的时候会出现一个问题,程序会生成一个临时包并去修改之前存在的同名压缩文件,最后修改不成功且会抛出异常:ZipException: cannot rename modified zip file最后只留下一个临时包, 建议在生成的时候添加判断 避免出现这种错误

    

示例4 创建加密压缩包

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public  class  AddFilesWithAESEncryption {
      
     public  AddFilesWithAESEncryption() {
          
         try  {
             ZipFile zipFile =  new  ZipFile( "c:\\ZipTest\\AddFilesWithAESZipEncryption.zip" );
  
             ArrayList<File> filesToAdd =  new  ArrayList<File>();
             filesToAdd.add( new  File( "c:\\ZipTest\\sample.txt" ));
             filesToAdd.add( new  File( "c:\\ZipTest\\myvideo.avi" ));
             filesToAdd.add( new  File( "c:\\ZipTest\\mysong.mp3" ));
              
             ZipParameters parameters =  new  ZipParameters();
             parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
              
             parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); 
             parameters.setEncryptFiles( true );
              
             parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
              
  
             parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
             parameters.setPassword( "123" );
      
             zipFile.addFiles(filesToAdd, parameters);
         catch  (ZipException e) {
             e.printStackTrace();
         }
     }
      
     public  static  void  main(String[] args) {
         new  AddFilesWithAESEncryption();
     }
      
}

加密压缩包后打开时需要输入密码,与rar相同:

示例5 创建分卷压缩包

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public  class  CreateSplitZipFile {
      
     public  CreateSplitZipFile() {
          
         try  {
          
             ZipFile zipFile =  new  ZipFile( "c:\\ZipTest\\CreateSplitZipFile.zip" );
              
  
             ArrayList<File> filesToAdd =  new  ArrayList<File>();
             filesToAdd.add( new  File( "c:\\ZipTest\\sample.txt" ));
             filesToAdd.add( new  File( "c:\\ZipTest\\myvideo.avi" ));
             filesToAdd.add( new  File( "c:\\ZipTest\\mysong.mp3" ));
              
             ZipParameters parameters =  new  ZipParameters();
             parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
              
             parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
              
             zipFile.createZipFile(filesToAdd, parameters,  true 65536 );
         catch  (ZipException e) {
             e.printStackTrace();
         }
     }
      
     /**
      * @param args
      */
     public  static  void  main(String[] args) {
         new  CreateSplitZipFile();
     }
  
}
  • 执行程序后会根据设置大小生成多个  压缩包名.z + 数量编号文件,如下图:

  • 如果已经存在同名压缩包,则会抛出异常提示已经存在:ZipException: zip file: c:\ZipTest\CreateSplitZipFile.zip already exists. To add files to existing zip file use addFile method
  • 需要进行分卷压缩的大小,不能小于规定的65536 bytes

示例6 通过流的方式添加文件到压缩包中

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public  class  AddStreamToZip {
      
     public  AddStreamToZip() {
          
         InputStream is =  null ;
          
         try  {
             ZipFile zipFile =  new  ZipFile( "c:\\ZipTest\\AddStreamToZip.zip" );
  
             ZipParameters parameters =  new  ZipParameters();
             parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
             parameters.setFileNameInZip( "yourfilename.txt" );
             parameters.setSourceExternalStream( true );
              
             is =  new  FileInputStream( "c:\\ZipTest\\sample.txt" );
             zipFile.addStream(is, parameters);
              
         catch  (Exception e) {
             e.printStackTrace();
         finally  {
             if  (is !=  null ) {
                 try  {
                     is.close();
                 catch  (IOException e) {
                     e.printStackTrace();
                 }
             }
         }
     }
      
     public  static  void  main(String[] args) {
         new  AddStreamToZip();
          
     }
      
      
}

示例7 解压压缩文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public  class  ExtractAllFiles {
      
     public  ExtractAllFiles() {
          
         try  {
             ZipFile zipFile =  new  ZipFile( "c:\\ZipTest\\ProgressInformation.zip" );
             zipFile.extractAll( "c:\\ZipTest1" );
              
         catch  (ZipException e) {
             e.printStackTrace();
         }
          
     }
  
     /**
      * @param args
      */
     public  static  void  main(String[] args) {
         new  ExtractAllFiles();
     }
  
}
  • 如果解压的文件需要密码,可以添加以下代码:
  • ?
    1
    2
    3
    4
    if  (zipFile.isEncrypted()) {
                     // if yes, then set the password for the zip file                  zipFile.setPassword( "test123!" );
                 }
  • 在进行解压缩时需要判断文件是否为加密压缩,否则会抛出异常:ZipException: empty or null password provided for AES Decryptor

压缩效率

   ZIP4J提供5中压缩算法:

  1.     DEFLATE_LEVEL_FASTEST 
  2.     DEFLATE_LEVEL_FASTEST
  3.     DEFLATE_LEVEL_NORMAL
  4.     DEFLATE_LEVEL_MAXIMUM
  5.     DEFLATE_LEVEL_ULTRA

   根据API提供的几种不同压缩级别进行测试(文件夹压缩),测试结果如下:

   一个180M的文件夹压缩后

  •    WinRAR 30秒 - 78.7 MB ; 
  •    NORMAL - 18 秒 91.2 MB  ;
  •    FAST 13秒 -93.1 MB;
  •    FASTEST - 最快速10 秒94.7 MB 
  •    MAXIMUM 23 秒 - 90.7 MB;
  •    ULTRA -50 90.6 MB

    与WinRAR 相比较来说,压缩时间还是很不错 但对文件的压缩大小来说还是WINRAR要强一些 (各人电脑配置不同 压缩的时间这些也不同)

     以上便是ZIP4J提供的一些常用的工具方法,总结在此,方便自己与大家使用。如果有更好的工具或者有不正确的地方欢迎大家指出!

参考文章1:http://www.cnblogs.com/sydeveloper/archive/2013/05/14/3078295.html   AJAX实现文件下载

参考文章2:http://blog.csdn.net/educast/article/details/38755287  ZIP文件压缩与解压缩学习

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值