gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 08:30:34 25 4
gpt4 key购买 nike

我正在尝试使用 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();
}
}

最佳答案

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

  1. zos 被声明为 servlet 实例变量。这不是线程安全的。它在多个请求之间共享。您可能面临后续请求在未完成时覆盖前一个请求的风险。

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

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

我认为#2 是主要原因。您不需要ByteArrayOutputStream。这只是不必要的内存占用。只需将 response.getOutputStream() 包装在 ZipOutputStream 中即可。

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

关于java - 使用 servlet 下载 zip 文件会返回损坏的 zip,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3503769/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com