关于jsp打包zip文件下载的问题,请帮忙解决。

我现在需要在项目中实现对多个文件打包成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吧

或者先写到文件上给链接