Spring MVC字节数组转ZipOutputStream及下载Zip无数据问题求助
解决Spring MVC中字节数组转ZipOutputStream时文件为空的问题
嘿,我来帮你搞定这个问题!你现在遇到的zip文件下载后内容为空的问题,核心原因很明确——你的代码只把ZipEntry的元信息写到了输出流里,完全没复制每个文件的实际内容,所以解压后所有文件都是0字节。
问题根源拆解
你当前的代码逻辑是:从数据库拿到zip字节数组,打开ZipInputStream遍历每个条目,然后直接把原ZipEntry放到ZipOutputStream里就完事了。但zipOutputStream.putNextEntry(ent)只是在输出的zip里创建了一个文件条目,没有把原zip里该文件的内容写进去,自然每个文件都是空的。
修复后的完整代码
我给你调整了代码,用Java的try-with-resources自动管理流(避免手动关流的坑),同时加上了关键的内容复制逻辑:
@RequestMapping(value = ApplicationConstants.ServiceURLS.TRANSLATIONS + "/{resourceId}/attachments", produces = "application/zip") public void attachments(HttpServletResponse response, @PathVariable("resourceId") Long resourceId) throws IOException { TtTranslationCollection tr = translationManagementDAO.getTranslationCollection(resourceId); byte[] fileData = tr.getFile(); // 配置响应头,确保浏览器正确识别zip文件 response.setStatus(HttpServletResponse.SC_OK); response.setContentType("application/zip"); response.addHeader("Content-Disposition", "attachment; filename=\"attachments.zip\""); // try-with-resources会自动关闭所有实现AutoCloseable的流,不用手动调用close() try (ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(fileData)); ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream())) { ZipEntry currentEntry; // 用缓冲区复制内容,比单字节读取效率高很多 byte[] buffer = new byte[4096]; int bytesRead; while ((currentEntry = zipStream.getNextEntry()) != null) { // 建议创建新的ZipEntry,避免复用原条目可能带来的元数据异常 ZipEntry newZipEntry = new ZipEntry(currentEntry.getName()); zipOutputStream.putNextEntry(newZipEntry); // 核心步骤:把原zip里的文件内容逐块复制到输出流 while ((bytesRead = zipStream.read(buffer)) != -1) { zipOutputStream.write(buffer, 0, bytesRead); } // 关闭当前条目,释放资源 zipOutputStream.closeEntry(); zipStream.closeEntry(); } } }
几个关键改进点
- 添加内容复制逻辑:用缓冲区循环读取原ZipInputStream的内容,写入ZipOutputStream,这是解决空文件的核心。
- try-with-resources自动关流:再也不用担心漏关流或者关流顺序错了导致的资源泄漏问题,Java会帮你处理。
- 创建新的ZipEntry:直接复用原ZipEntry可能会携带一些内部状态,新建条目更稳妥。
- 明确设置ContentType:显式指定
application/zip,确保浏览器能正确识别下载的文件类型。
额外小提示
如果还是有问题,可以先验证数据库里的字节数组是不是有效的zip文件——比如把字节数组写到本地文件,看看能不能正常解压。如果本地也打不开,那可能是存入数据库的时候就出问题了。
内容的提问来源于stack exchange,提问作者Amol Patil
相关产品推荐
相关产品推荐

