压缩(zipped)文件夹是无效的Java

问题描述 投票:3回答:2

我正在尝试使用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
2个回答
4
投票

7Zip可以打开各种各样的拉链格式,并且相对容忍奇怪。 Windows双击需要相对特定的格式,并且容忍度要低得多。

您需要查找zip format,然后使用十六进制编辑器(例如Hex Editor Neo)查看您的文件(和“好”文件),看看可能出错的地方。

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


3
投票

可能是缺少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();

最后是finishclosethe zip。

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

     in.close();

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

对于具有例如西里尔字母的文件名,最好添加像UTF-8这样的Unicode字符集。事实上,让UTF-8成为世界范围内的世界语标准。

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

© www.soinside.com 2019 - 2024. All rights reserved.