Web 應用常需將多個檔案打包成 ZIP 並直接以串流回應下載,無需落地儲存。本文示範使用 ZipOutputStream 壓縮多檔案至 ByteArrayOutputStream,再寫入 HTTP Response。
public ByteArrayOutputStream filesToZip(List filePaths, String zipName, String baseDir) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
for (String path : filePaths) {
File file = new File(baseDir, path);
try (FileInputStream fis = new FileInputStream(file)) {
zos.putNextEntry(new ZipEntry(file.getName()));
byte[] buf = new byte[1024];
int len;
while ((len = fis.read(buf)) > 0) zos.write(buf, 0, len);
zos.closeEntry();
}
}
zos.finish(); // 重要:完成 ZIP 結構
} catch (IOException e) { e.printStackTrace(); }
return baos;
}
@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
List files = Arrays.asList("file1.txt", "file2.png", "data.xls");
ByteArrayOutputStream zipStream = filesToZip(files, "export.zip", "C:/temp/");
resp.setContentType("application/zip");
resp.setHeader("Content-Disposition", "attachment; filename=\"export.zip\"");
resp.setContentLength(zipStream.size());
try (OutputStream out = resp.getOutputStream()) {
zipStream.writeTo(out);
}
}
}
zos.finish() 必須在關閉前呼叫,寫入中央目錄結構。ByteArrayOutputStream 適合中小檔案;大檔案應直接寫入 resp.getOutputStream() 避免 OOM。URLEncoder.encode(name, "UTF-8")。