因为项目要支持上传zip包,默认把包中的index.html当成首页来展示,于是星期五做了个Java解压zip文件的模块,没啥难度,要注意的是对于文件夹的特殊处理,避免变成okb的文件;另外由于通常我们的打包习惯是把一个文件夹压缩,这样解压后仍有一层文件夹,进入文件夹之后才是压缩包中的文件,这里也做了处理,下面把代码记录下,以便查阅。
package com.syni.im800.kb.common.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* 对上传的ZIP文件进行解压
* @author linshutao
* */
public class UnpackZipUtil {
Log log = LogFactory.getLog(getClass());
private static UnpackZipUtil unpackZipUtil;
/**
* 获取UnpackZipUtil实例
* */
public static synchronized UnpackZipUtil getUtilInstance(){
if(unpackZipUtil == null){
unpackZipUtil = new UnpackZipUtil();
}
return unpackZipUtil;
}
/**
* 解压文件,zip文件中含有index.html/index.htm,直接返回该名字,该方法用于解压
* @param fromFileInputStream: 文件输入流
* @param toFileFolder 解压后存放的文件夹
* */
public String file2Html(InputStream fromFileInputStream, File toFileFolder){
/**
* 由fromFileInputStream构建输入文件
* */
Date date = new Date();
SimpleDateFormat sdf =new SimpleDateFormat("yyyyMMddHHmmss");
String timesuffix = sdf.format(date);
String zipFileName = "zipfile"+timesuffix+".zip";
File zipInputFile = new File(toFileFolder.toString()+File.separatorChar+zipFileName);
try {
OutputStream os = new FileOutputStream(zipInputFile);
int bytesRead = 0;
byte[] buffer = new byte[1024 * 8];
while ((bytesRead = fromFileInputStream.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
fromFileInputStream.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
boolean hasIndexFile = false;
String returnStr = "";
try {
ZipFile zipfile = new ZipFile(zipInputFile);
ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipInputFile));
ZipEntry zipEntry = null;
log.info("开始解压...");
int i = 0;
//存储第一次解压的文件,考虑处理解压后仍有一层文件夹的情况
ZipEntry firstZipEntry = null;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
i++;
String currFileName = zipEntry.getName();
if(i==1){
firstZipEntry = new ZipEntry(zipEntry);
}
if(currFileName.equalsIgnoreCase("index.html") || currFileName.equalsIgnoreCase("index.htm")){
returnStr = currFileName;
hasIndexFile = true;
}
log.info(i+":"+currFileName);
if(zipEntry.isDirectory()){}
File temp = new File(toFileFolder, currFileName);
if (!temp.getParentFile().exists()){
temp.getParentFile().mkdirs();
}
//不对文件夹进行操作,否则文件夹会变成0kb的文件
if(zipEntry.isDirectory()){
continue;
}
OutputStream os = new FileOutputStream(temp);
// 通过ZipFile的getInputStream方法拿到具体的ZipEntry的输入流
InputStream is = zipfile.getInputStream(zipEntry);
int len = 0;
while ((len = is.read()) != -1)
os.write(len);
os.close();
is.close();
}
//没检测到index.html/index.htm,且第一个解压的文件是文件夹,可判断为解压后仍有一层文件夹
if(!hasIndexFile && firstZipEntry.isDirectory()){
File folder = new File(toFileFolder.getPath()+File.separatorChar+firstZipEntry.getName());
File[] files = folder.listFiles();
for(int j=0;j<files.length;++j){
String filename = files[j].getName();
if(filename.equalsIgnoreCase("index.html") || filename.equalsIgnoreCase("index.htm")){
hasIndexFile = true;
//文件夹解压后文件夹名称已带有文件分隔符
returnStr = firstZipEntry.getName()+filename;
}
}
}
zipfile.close();
zipInputStream.close();
zipInputFile.delete();//删除上传的zip文件
if(!hasIndexFile){
log.info("错误:该压缩文件中没有index.html!请重新上传!");
return ContentFromFileUtil.FAILED_BY_NO_INDEX_FOR_ZIP;
}
} catch (ZipException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return returnStr;
}
}