Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Basically you just need to construct a new <code>ZipOutputStream</code> around <code>response.getOutputStream()</code> and then add every <code>InputStream</code> from the DB as new <code>ZipEntry</code>. To improve performance, you can wrap the <code>response.getOutputStream()</code> in a <code>BufferedOutputStream</code> beforehand and the <code>InputStream</code> in a <code>BufferedInputStream</code> and use a <code>byte[]</code> buffer.</p> <p>Here's a basic example:</p> <pre><code>package com.example; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ZipFileServlet extends HttpServlet { private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB. private YourFileDAO yourFileDAO = YourDAOFactory.getYourFileDAO(); @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String[] fileIds = request.getParameterValues("fileId"); response.setContentType("application/zip"); response.setHeader("Content-Disposition", "attachment; filename=\"allfiles.zip\""); ZipOutputStream output = null; byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; try { output = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE)); for (String fileId : fileIds) { YourFileItem item = yourFileDAO.find(fileId); if (item == null) continue; // Handle yourself. The fileId may be wrong/spoofed. InputStream input = null; try { input = new BufferedInputStream(item.getInputStream(), DEFAULT_BUFFER_SIZE); output.putNextEntry(new ZipEntry(item.getName())); for (int length = 0; (length = input.read(buffer)) &gt; 0;) { output.write(buffer, 0, length); } output.closeEntry(); } finally { if (input != null) try { input.close(); } catch (IOException logOrIgnore) { /**/ } } } } finally { if (output != null) try { output.close(); } catch (IOException logOrIgnore) { /**/ } } } } </code></pre> <p>which can be invoked by a form like this:</p> <pre><code>&lt;form action="zipFile" method="post"&gt; &lt;input type="checkbox" name="fileId" value="1"&gt; foo.exe&lt;br&gt; &lt;input type="checkbox" name="fileId" value="2"&gt; bar.pdf&lt;br&gt; &lt;input type="checkbox" name="fileId" value="3"&gt; waa.doc&lt;br&gt; &lt;input type="checkbox" name="fileId" value="4"&gt; baz.html&lt;br&gt; &lt;input type="submit" value="download zip"&gt; &lt;/form&gt; </code></pre> <p>That said, do in <strong>no way</strong> use <code>ByteArrayInputStream/ByteArrayOutputStream</code> as some here may suggest. Those are namely backed by a raw <code>byte[]</code>. You may risk that that your application breaks when the size of all of the files (from all concurrent users!) together inside bytearrays is larger than the available server memory. You already have a stream from the DB and a stream to the response. Just pipe them through a small byte buffer in a read/write loop. You don't need to get hold of the entire inputstream in a (under the hood) massive byte buffer and then write it away to the outputstream.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload