【问题标题】:The compressed (zipped) folder is invalid Java压缩(压缩)文件夹是无效的 Java
【发布时间】:2012-01-23 13:43:11
【问题描述】:

我正在尝试使用 ZipOutputStream 将文件从服务器压缩到一个文件夹中。 存档下载后双击打不开。出现错误“压缩(压缩)文件夹无效”。但是,如果我从上下文菜单-> 7zip-> 打开文件打开它,它可以正常工作。问题的原因可能是什么?

sourceFileName="./file.txt"'
                    sourceFile = new File(sourceFileName);

                    try {
                        // set the content type and the filename
                       responce.setContentType("application/zip");
                        response.addHeader("Content-Disposition", "attachment; filename=" + sourceFileName + ".zip");
                        responce.setContentLength((int) sourceFile.length());


                        // get a ZipOutputStream, so we can zip our files together
                        ZipOutputStream outZip = new ZipOutputStream((responce.getOutputStream());

                        // Add ZIP entry to output stream.
                        outZip.putNextEntry(new ZipEntry(sourceFile.getName()));

                        int length = 0;
                        byte[] bbuf = new byte[(int) sourceFile.length()];

                        DataInputStream in = new DataInputStream(new FileInputStream(sourceFile));
                        while ((in != null) && ((length = in.read(bbuf)) != -1)) {
                            outZip.write(bbuf, 0, length);
                        }

                        outZip.closeEntry();
                        in.close();
                        outZip.flush();
                        outZip.close();

【问题讨论】:

    标签: java


    【解决方案1】:

    7Zip 可以打开多种 zip 格式,并且对奇怪的东西比较宽容。 Windows 双击需要相对特定的格式,而且容忍度要低得多。

    您需要查找zip format,然后使用十六进制编辑器(例如 Hex Editor Neo)查看您的文件(以及“好的”文件),看看可能出了什么问题。

    (一种可能是您使用了错误的压缩算法。还有其他几种变体需要考虑,尤其是您是否生成“目录”。)

    【讨论】:

    • 7Zip 在 Windows 上的资源管理器菜单上有一个“测试存档”选项可能会有所帮助
    【解决方案2】:

    可能是缺少close。可能是 Windows 无法处理 zip 中的路径编码。可能是 Windows 对目录结构有困难,或者路径名包含(反)斜杠。所以这是侦探工作,尝试不同的文件。如果您立即将 zip 流式传输到 HTTP 响应,则必须将 finish 称为 i.o。 close.


    代码发布后:

    问题在于setContentLength 给出了原始文件大小。但是当给出时,它应该给出压缩后的大小。

    DataInputStream 是不需要的,这里应该做一个readFully

        responce.setContentType("application/zip");
        response.addHeader("Content-Disposition", "attachment; filename=file.zip");
    
         //Path sourcePath = sourceFile.toPath();
         Path sourcePath = Paths.get(sourceFileName);
    
         ZipOutputStream outZip = new ZipOutputStream((responce.getOutputStream(),
                StandardCharsets.UTF-8);
    
         outZip.putNextEntry(new ZipEntry(sourcePath.getFileName().toString()));
         Files.copy(sourcePath, outZip);
         outZip.closeEntry();
    

    finishclose最后的 zip。

         outZip.finish();
         //outZip.close();
    
         in.close();
    

    我不确定(关于最佳代码风格)是否已经自己close the response output stream。 但是当不关闭 finish() 必须调用时,flush() 是不够的,因为最后数据会写入 zip。

    对于带有例如西里尔字母的文件名,最好添加一个 Unicode 字符集,如 UTF-8。事实上,让 UTF-8 成为全世界的世界语标准。

    最后一点:如果只有一个文件可以使用GZipOutputstream 代替file.txt.gz 或查询浏览器的功能(请求参数)并将其压缩为file.txt

    【讨论】:

    • @Ксения Шапошникова 欢迎;我很好奇
    • ContentDisposition 标头中的文件名应该只是没有路径的“file.zip”。不应给出 Content-Length,因为您不知道(已压缩)。你应该用 outZip.finish 替换 outZip.close;关闭 JEE 服务器。
    • 对于一个文件,你可以使用GZipOutputStream,创建file.txt.gz。
    • DataInputSteam 用于特殊情况 int/long 和其他结构化数据。也许 BufferedInputStream 可以。 in != null 可以去掉。
    • 我已遵循所有建议,但使用 GZipOutputStream 除外。但它还没有工作。如果我尝试将相同的代码粘贴到仅从本地机器获取文件的项目中,将其打包并保存在本地机器上(在这种情况下,服务器与客户端在同一台机器上)一切正常。当我使用远程服务器时,也许有一些特殊之处?
    猜你喜欢
    • 2013-03-09
    • 2010-09-05
    • 1970-01-01
    • 2010-12-14
    • 2012-06-19
    • 2013-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多