我正在尝试使用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();
7Zip可以打开各种各样的拉链格式,并且相对容忍奇怪。 Windows双击需要相对特定的格式,并且容忍度要低得多。
您需要查找zip format,然后使用十六进制编辑器(例如Hex Editor Neo)查看您的文件(和“好”文件),看看可能出错的地方。
(一种可能性是您使用了错误的压缩算法。还有其他几种变体需要考虑,特别是您是否生成“目录”。)
可能是缺少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();
最后是finish
或close
the 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
。