Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 下载zip文件会使用servlet返回损坏的zip_Java_Servlets_Zip_Download - Fatal编程技术网

Java 下载zip文件会使用servlet返回损坏的zip

Java 下载zip文件会使用servlet返回损坏的zip,java,servlets,zip,download,Java,Servlets,Zip,Download,我正在尝试使用servlet创建一个zip文件,但它返回了一个损坏的zip文件,下面是我正在创建zip的zipcontents函数中的代码,有人能帮我吗。提前谢谢 public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { ByteArrayOutputStream bout = new ByteArrayOutputStrea

我正在尝试使用servlet创建一个zip文件,但它返回了一个损坏的zip文件,下面是我正在创建zip的zipcontents函数中的代码,有人能帮我吗。提前谢谢

public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException,
    IOException {

    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    res.setContentType("application/zip");
    res.setHeader("Content-Disposition", "attachment; filename=output.zip;");

    fsep = File.separator;
    rootDir = new File(getServletContext().getRealPath("Projects" + File.separator + "amrurta"));
    File list[] = rootDir.listFiles();
    zos = new ZipOutputStream(bout);
    zipContents(list, rootDir.getName() + fsep);
    zos.close();
    res.getWriter().println(bout.toString());
}

public void zipContents(File[] file, String dir) {
    // dir - directory in the zip file
    byte[] buffer = new byte[4096];
    try {

        for (int i = 0; i < file.length; i++) { // zip files
            if (file[i].isFile()) {
                fis = new FileInputStream(file[i]);
                zos.putNextEntry(new ZipEntry(dir + file[i].getName()));
                // shows how its stored
                // System.out.println(dir+file[i].getName());
                int bytes_read;
                while ((bytes_read = fis.read(buffer)) != -1)
                    zos.write(buffer, 0, bytes_read);

                fis.close();
            }
        } // for

        // create empty dir if theres no files inside
        if (file.length == 1)
            zos.putNextEntry(new ZipEntry(dir + fsep)); // this part is erroneous i think

        for (int i = 0; i < file.length; i++) { // zip directories
            if (file[i].isDirectory()) {
                File subList[] = file[i].listFiles();

                // for dir of varying depth
                File unparsedDir = file[i];
                String parsedDir = fsep + file[i].getName() + fsep; // last folder
                while (!unparsedDir.getParentFile().getName().equals(rootDir.getName())) {
                    unparsedDir = file[i].getParentFile();
                    parsedDir = fsep + unparsedDir.getName() + parsedDir;
                }
                parsedDir = rootDir.getName() + parsedDir; // add input_output as root

                zipContents(subList, parsedDir);
            }
        } // for

    } catch (IOException ioex) {
        ioex.printStackTrace();
    }
}
public void doGet(HttpServletRequest-req,HttpServletResponse-res)抛出ServletException,
IOException{
ByteArrayOutputStream bout=新建ByteArrayOutputStream();
res.setContentType(“应用程序/zip”);
res.setHeader(“内容处置”、“附件;文件名=output.zip;”);
fsep=File.separator;
rootDir=新文件(getServletContext().getRealPath(“Projects”+File.separator+“amrurta”);
文件列表[]=rootDir.listFiles();
zos=新ZipoutStream(布特);
zipContents(list,rootDir.getName()+fsep);
zos.close();
res.getWriter().println(bout.toString());
}
公共void ZipContent(文件[]文件,字符串目录){
//dir-zip文件中的目录
字节[]缓冲区=新字节[4096];
试一试{
对于(int i=0;i
代码中有太多问题。出现的主要问题有:

  • zos
    被声明为servlet实例变量。这不是线程安全的。它已在多个请求之间共享。如果子用户请求尚未完成,则可能会覆盖上一个请求

  • 二进制ZIP内容已通过
    bout.toString()
    转换为字符数据。这肯定会损坏二进制数据。您应该使用通常的
    InputStream#read()
    /
    OutputStream#write()
    循环将二进制数据作为二进制数据写入

  • 代码不会在每个条目末尾调用
    zos.closeEntry()

  • 我认为#2是主要原因。您不需要通过tearrayoutputstream
    。这只是一个不必要的记忆猪。只需将
    响应.getOutputStream()
    包装在
    ZipOutputStream

    ZipOutputStream output = new ZipOutputStream(response.getOutputStream());
    zipFiles(directory.listFiles(), output);
    output.close();
    

    代码中有太多问题。出现的主要问题有:

  • zos
    被声明为servlet实例变量。这不是线程安全的。它已在多个请求之间共享。如果子用户请求尚未完成,则可能会覆盖上一个请求

  • 二进制ZIP内容已通过
    bout.toString()
    转换为字符数据。这肯定会损坏二进制数据。您应该使用通常的
    InputStream#read()
    /
    OutputStream#write()
    循环将二进制数据作为二进制数据写入

  • 代码不会在每个条目末尾调用
    zos.closeEntry()

  • 我认为#2是主要原因。您不需要通过tearrayoutputstream
    。这只是一个不必要的记忆猪。只需将
    响应.getOutputStream()
    包装在
    ZipOutputStream

    ZipOutputStream output = new ZipOutputStream(response.getOutputStream());
    zipFiles(directory.listFiles(), output);
    output.close();
    

    另一个可能的原因是应用服务器和编译servlet的编译器的JVM版本不同。
    非常罕见的问题,但很难理解。

    另一个可能的原因是应用服务器和编译servlet的编译器的JVM版本不同。 非常罕见的问题,但很难理解。

    您可以这样创建
    ZipOutputStream zipOut=newzipoutpstream(res.getOutputStream())
    您写入zip条目的每个zip条目都将流式传输回调用者。

    您可以这样创建
    ZipOutputStream zipOut=newzipoutpstream(res.getOutputStream())
    您写入zip条目的每个zip条目都将流式传输回调用者