在實際開發過程中,會經常遇到下載附件或者導出報表的情況,有時候文件會比較多,用戶更希望多個文件可以一起打包進行下載。這時就需要實現兩部分功能:一部分是多個文件的打包處理,一部分是壓縮文件的下載功能。
對於壓縮文件的下載,可查看我的另一篇博文(SpringMVC下打包文件的下載),本文主要提供多個文件的壓縮與解壓的例子。樣例完全基於JDK自帶的IO流處理類,主要相關類爲ZipInputStream和ZipOutputStream,使用JDK API已經能夠滿足壓縮與解壓的需求。我看網上有不少提到壓縮中文亂碼的問題,建議用ant.jar中包的ZIP處理類進行處理,我進行了相關測試:使用JDK1.6進行壓縮會出現壓縮包中的文件中文名亂碼,但是使用JDK1.7或者JDK1.8不會亂碼。
所以本樣例正常運行需要使用JDK1.7+的版本。
另注:本樣例仍然有個問題有待解決:我分別使用txt文件、excel文件、word文件進行壓縮測試,壓縮正常,使用WinRAR工具解壓後文件也能正常查看。但是使用JDK的IO流解壓後,只有txt文件查看正常,excel與word文件都損壞了,無法正常查看。這個問題仍未找到原因與解決方案,若有大神告知,感激不盡。
下面直接上代碼:
一、壓縮與解壓工具類
ZipUtils.java
package research.j2se.io;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
* 使用JDK自帶的Zip處理類進行文件的壓縮與解壓
*
*/
public class ZipUtils {
/**
* 壓縮文件(一個或多個)到指定壓縮包
*/
public static void zip( String targetFilePath, String ... sourceFilePaths){
if( sourceFilePaths == null || sourceFilePaths.length == 0 ){
return;
}
try {
File targetFile = new File(targetFilePath);
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(targetFile));
BufferedInputStream bis = null;
byte [] buffer = new byte[512];
for( int i = 0; i < sourceFilePaths.length; i++ ){
File sourceFile = new File(sourceFilePaths[i]);
if( sourceFile.exists() ){
//目標文件不存在則創建文件
if( ! targetFile.exists() ){
targetFile.createNewFile();
}
String sourceFileName = sourceFile.getName();
ZipEntry entry = new ZipEntry(sourceFileName);
//設置壓縮包的入口
zos.putNextEntry(entry);
bis = new BufferedInputStream(new FileInputStream(sourceFile));
while( bis.read(buffer) != -1){
zos.write(buffer);
}
}
}
bis.close();
zos.flush();
zos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 解壓文件到指定目錄
*/
public static void unzip(String targetDirPath, String ... sourceFilePaths){
if( sourceFilePaths == null || sourceFilePaths.length == 0 ){
return;
}
//解壓目錄不存在則創建
File targetDir = new File(targetDirPath);
if( ! targetDir.exists() ){
targetDir.mkdirs();
}
try {
byte [] buffer = new byte[512];
for( int i = 0; i < sourceFilePaths.length; i++ ){
File sourceFile = new File(sourceFilePaths[i]);
ZipInputStream zis = new ZipInputStream(new FileInputStream(sourceFile));
ZipEntry entry = null;
//遍歷壓縮文件的各個入口
while( (entry=zis.getNextEntry()) != null ){
String fileName = entry.getName();
//創建對應的文件
File file = new File(targetDirPath+File.separator + fileName);
if( ! file.exists() ){
file.createNewFile();
}
//進行文件的寫入
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file,true));
while( zis.read(buffer) != -1 ){
bos.write(buffer);
}
zis.closeEntry();
bos.flush();
bos.close();
}
zis.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch( Exception e ){
e.printStackTrace();
}
}
}
二、壓縮與解壓測試類
JdkZipUtilsTest.java
package research.j2se.io;
import junit.framework.TestCase;
import research.j2se.io.ZipUtils;
/**
* jdk壓縮解壓工具類測試
*/
public class JdkZipUtilsTest
extends TestCase
{
/**
* 測試壓縮文件
*/
public void testZip()
{
String targetFilePath = "src/main/resources/ziptarget/zip/壓縮.zip";
String sourceFilePath1 = "src/main/resources/zipsource/unzip/測試1.xlsx";
String sourceFilePath2 = "src/main/resources/zipsource/unzip/測試2.txt";
String sourceFilePath3 = "src/main/resources/zipsource/unzip/測試3.docx";
ZipUtils.zip(targetFilePath, sourceFilePath1,sourceFilePath2,sourceFilePath3);
}
/**
* 測試解壓文件(這裏Excel文件解壓無法打開,使用解壓工具可以打開)
*/
public void testUnzip(){
String targetDirPath = "src/main/resources/ziptarget/unzip";
String sourceFilePath1 = "src/main/resources/zipsource/zip/壓縮.zip";
ZipUtils.unzip(targetDirPath, sourceFilePath1);
}
}
本樣例測試通過。若要查看完整源碼,可訪問:https://github.com/wdmcygah/research-J2SE.git