我现在需要在项目中实现对多个文件打包成zip下载。从网上找到一段代码如下,可用,但是,会提示getOutputStream已经被called的异常。不知道哪里的问题,请帮忙解决。
另外这个代码是先保存为文件,然后再向reaponse输出流的,有没有直接压缩后就输出不保存本地文件的方法,请指教。
另外,如果能够实现一次压缩多个文件夹就更好了。
还有,zip文件是不是可以附带文本性的注释的呢?
[code="java"]
package com.xinkao.util;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.tools.zip.*;
import javax.servlet.http.HttpServletResponse;
public class JspFileDownload {
/** request object */
private HttpServletResponse response = null;
/** file type: -1 un-setting; 0 normal file; 1 zip file ;2 stream*/
private int fileType = -1;
/** file name to be displayed */
private String disFileName = null;
/** zip file path */
private String zipFilePath = null;
/** file to be zipped */
private String[] zipFileNames = null;
private boolean zipDelFlag = false;
/** file to be downloaded */
private String downFileName = null;
/** error code 0 */
private static final int PROCESS_OK = 0;
/** error code 1 */
private static final int RESPONSE_IS_NULL = 1;
/** error code 2 */
private static final int UNSET_DOWNLOADTYPE = 2;
/** error code 3 */
private static final int UNSET_DIS_FILE_NAME = 3;
/** error code 4 */
private static final int UNSET_DOWN_FILE_NAME = 4;
/** error code 9 */
private static final int IO_EXCEPTION = 9;
/**
* set response object
* @param response response Object
*/
public void setResponse(HttpServletResponse response){
this.response = response;
}
/**
* set file type 0 normal file; 1 zip file ;2 stream
* @param fileType
*/
public void setDownType(int fileType){
this.fileType = fileType;
}
/**
* set display file name
* @param fileName
*/
public void setDisFileName(String fileName){
this.disFileName = fileName;
}
/**
* set zip file path
* @param fileNames
*/
public void setZipFilePath( String path ){
this.zipFilePath = path;
}
public void setZipDelFlag(boolean b){
this.zipDelFlag = b;
}
/**
* set zip file names
* @param fileNames
*/
public void setZipFileNames(String[] fileNames){
this.zipFileNames = fileNames;
}
/**
* set download file name
* @param fileName
*/
public void setDownFileName(String fileName){
this.downFileName = fileName;
}
/**
* set file content
* @param fileContent
*/
public int setFileContent(String fileContent){
try{
byte[] buffs = fileContent.getBytes("GBK");
response.getOutputStream().write(buffs);
}catch(IOException e){
return IO_EXCEPTION;
}
return PROCESS_OK;
}
/**
* set file content
* @param fileContent
*/
public int setFileContent(byte[] fileContent){
try{
response.getOutputStream().write(fileContent);
}catch(IOException e){
return IO_EXCEPTION;
}
return PROCESS_OK;
}
/**
* set file content end
*
*/
public int setFileContentEnd(){
try{
response.getOutputStream().close();
}catch(IOException e){
return IO_EXCEPTION;
}
return PROCESS_OK;
}
/**
* main process
* @return
*/
public int process(){
int status = PROCESS_OK;
status = preCheck();
if ( status != PROCESS_OK )
return status;
String fileName = disFileName;
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition","attachment;filename=\"" + fileName + "\"");
int BUFSIZE = 1024 * 8;
int rtnPos = 0;
byte[] buffs = new byte[ BUFSIZE ];
FileInputStream inStream = null;
ZipOutputStream zos = null;
InputStream is = null;
String filepath = null;
try{
if ( fileType == 0 || fileType == 1){
if ( fileType == 0 ){
filepath = downFileName;
}else{
filepath = zipFilePath + fileName;
String[] fileToZip = zipFileNames;
zos=new ZipOutputStream(new FileOutputStream(filepath));
ZipEntry ze=null;
byte[] buf=new byte[BUFSIZE];
int readLen=0;
for (int i= 0;i<fileToZip.length;i++){
File f= new File(fileToZip[i]);
ze=new ZipEntry(f.getName());
ze.setSize(f.length());
ze.setTime(f.lastModified());
zos.putNextEntry(ze);
is=new BufferedInputStream(new FileInputStream(f));
while ((readLen=is.read(buf, 0, BUFSIZE))!=-1) {
zos.write(buf, 0, readLen);
}
is.close();
}
zos.close();
}
inStream =new FileInputStream(filepath);
while((rtnPos=inStream.read(buffs)) >0)
response.getOutputStream().write(buffs,0,rtnPos);
response.getOutputStream().close();
inStream.close();
}
if ( zipDelFlag ){
File fToDel = new File(filepath);
fToDel.delete();
}
}catch(IOException e){
return IO_EXCEPTION;
}finally{
try{
if ( inStream != null ){
inStream.close();
inStream = null;
}
if ( zos != null ){
zos.close();
zos = null;
}
if ( is != null ){
is.close();
is = null;
}
}catch (IOException e){
}
}
return status;
}
/**
* pre check.
* @return
*/
private int preCheck(){
if ( response == null )
return RESPONSE_IS_NULL;
if ( disFileName == null || disFileName.trim().length() == 0 )
return UNSET_DIS_FILE_NAME;
if ( fileType == -1 )
return UNSET_DOWNLOADTYPE;
else if ( fileType == 0 ){
if ( downFileName == null || downFileName.trim().length() == 0 )
return UNSET_DOWN_FILE_NAME;
else{
if ( !isFile( downFileName ) )
return UNSET_DOWN_FILE_NAME;
}
}else if ( fileType == 1 ){
if ( zipFilePath == null || zipFilePath.length() == 0 )
return UNSET_DOWN_FILE_NAME;
else{
if ( !isDirect(zipFilePath) )
return UNSET_DOWN_FILE_NAME;
}
if ( zipFileNames == null || zipFileNames.length == 0 )
return UNSET_DOWN_FILE_NAME;
else{
for ( int i=0;i<zipFileNames.length;i++ ){
if ( zipFileNames[i] == null || zipFileNames[i].trim().length() == 0 )
return UNSET_DOWN_FILE_NAME;
else{
if ( !isFile( zipFileNames[i] ) )
return UNSET_DOWN_FILE_NAME;
}
}
}
}else if ( fileType == 2 ){
//doing nothing
}else{
return UNSET_DOWNLOADTYPE;
}
return PROCESS_OK;
}
private boolean isFile(String fileName){
File f = new File(fileName);
if (!f.exists() || !f.isFile())
return false;
return true;
}
private boolean isDirect(String filePath){
File f = new File(filePath);
if (!f.exists() || !f.isDirectory())
return false;
return true;
}
}
[/code]
不好意思,还有一个问题没有看到,
把
zos=new ZipOutputStream(new FileOutputStream(filepath));
改成
zos=new ZipOutputStream(response.getOutputStream());
然后把下面读文件输出部分的删除掉,就可以实现不写文件直接输出.
看看附件中的类吧专门处理zip的
package com.emice.common2.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.apache.tools.zip.ZipOutputStream;
public class ZipUtil {
private static void zip(
ZipOutputStream out,
File f,
String base,
boolean first) throws Exception {
if (first) {
if (f.isDirectory()) {
out.putNextEntry(new ZipEntry("/"));
base = base + f.getName();
first = false;
} else {
base = f.getName();
}
}
if (f.isDirectory()) {
File[] fl = f.listFiles();
if(!"".equals(base)){
base = base + "/";
}
for (int i = 0; i < fl.length; i++) {
zip(out, fl[i], base + fl[i].getName(), first);
}
} else {
out.putNextEntry(new ZipEntry(base));
FileInputStream in = null;
try{
in = new FileInputStream(f);
IOUtil.write(out, in, 1024*1024);
}finally{
IOUtil.close(in);
}
}
}
/*
* 解压文件
* unZip为解压路径1�7
*/
private static void unZip(
ZipFile zipFile,
File unZipRoot) throws Exception, IOException {
java.util.Enumeration e = zipFile.getEntries();
while (e.hasMoreElements()) {
ZipEntry zipEntry = (ZipEntry) e.nextElement();
if (zipEntry.isDirectory()) {
continue;
}
InputStream fis = null;
FileOutputStream fos = null;
try{
fis = zipFile.getInputStream(zipEntry);
File file = new File(unZipRoot,zipEntry.getName());
File parentFile = file.getParentFile();
parentFile.mkdirs();
fos = new FileOutputStream(file);
IOUtil.write(fos, fis, 1024*1024);
}finally{
IOUtil.close(fis);
IOUtil.close(fos);
}
}
}
public static void zip(File zipFileName, File inputFileOrFolderName) throws Exception {
ZipOutputStream out = null;
try{
out = new ZipOutputStream(new FileOutputStream(zipFileName));
out.setEncoding("gbk");
zip(out, inputFileOrFolderName, "", true);
}catch(Exception exp){
throw exp;
}finally{
IOUtil.close(out);
}
}
public static void zip(File zipFileName, File inputFileOrFolderName, boolean first) throws Exception {
ZipOutputStream out = null;
try{
out = new ZipOutputStream(new FileOutputStream(zipFileName));
out.setEncoding("gbk");
zip(out, inputFileOrFolderName, "", first);
}catch(Exception exp){
throw exp;
}finally{
IOUtil.close(out);
}
}
public static void unZip(File zipFile, File unZipFolder) throws Exception {
ZipFile zf = new ZipFile(zipFile, "gbk");
unZip(zf, unZipFolder);
}
// public static void zipFiles(List srcfile, File zipfile) {
// byte[] buf = new byte[1024];
// try {
// // Create the ZIP file
// ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipfile));
// // Compress the files
// for (File file : srcfile) {
// FileInputStream in = new FileInputStream(file);
// // Add ZIP entry to output stream.
// out.putNextEntry(new ZipEntry(file.getName()));
// // Transfer bytes from the file to the ZIP file
// int len;
// while ( (len = in.read(buf)) > 0) {
// out.write(buf, 0, len);
// }
// // Complete the entry
// out.closeEntry();
// in.close();
// }
// // Complete the ZIP file
// out.close();
// System.out.println("压缩完成.");
// }
// catch (IOException e) {
// e.printStackTrace();
// }
// }
public static void main(String[] args) throws Exception {
zip(new File("E:/test/test", "head.zip"), new File("E:/test/test/新建文件夹"), false);
// unZip(new File("E:/test/test/head.zip"), new File("E:/test/test/head"));
String encode = System.getProperty("file.encoding");
System.out.println("encode --------- "+encode);
}
}
你好,jsp里面有个标准对象叫做out,他会被tomcat默认创建,通过封装respose.getOutputStream()来实现,所以在jsp页面使用respose.getOutputStream()都会提示已经被调用过了.
Zip是可以添加注释的ZipOutputStream里有个setComment方法,你调用一下就可以添加了。
别用jsp,不小心有个空格回车啥的你就开始Output了,用servlet吧
或者先写到文件上给链接