Creating a zip on the fly with csv files inside

17,065

You can stream the ZIP file containing your CSVs as follows :

try {
    OutputStream servletOutputStream = httpServletResponse.getOutputStream(); // retrieve OutputStream from HttpServletResponse
    ZipOutputStream zos = new ZipOutputStream(servletOutputStream); // create a ZipOutputStream from servletOutputStream

    List<String[]> csvFileContents  = getContentToZIP(); // get the list of csv contents. I am assuming the CSV content is generated programmatically
    int count = 0;
    for (String[] entries : csvFileContents) {
        String filename = "file-" + ++count  + ".csv";
        ZipEntry entry = new ZipEntry(filename); // create a zip entry and add it to ZipOutputStream
        zos.putNextEntry(entry);

        CSVWriter writer = new CSVWriter(new OutputStreamWriter(zos));  // There is no need for staging the CSV on filesystem or reading bytes into memory. Directly write bytes to the output stream.
        writer.writeNext(entries);  // write the contents
        writer.flush(); // flush the writer. Very important!
        zos.closeEntry(); // close the entry. Note : we are not closing the zos just yet as we need to add more files to our ZIP
    }

    zos.close(); // finally closing the ZipOutputStream to mark completion of ZIP file
} catch (Exception e) {
    log.error(e); // handle error
}
Share:
17,065

Related videos on Youtube

ant-depalma
Author by

ant-depalma

Surfing and coding are equally fun to me, somehow.

Updated on June 04, 2022

Comments

  • ant-depalma
    ant-depalma almost 2 years

    I'm trying to create a zip file on the fly containing a bunch of csv files to return from a servlet and its very confusing. A little guidance would be great. Here are chunks of code I have that somehow need to work together:

    // output stream coming from httpResponse, thats all fine
    ZipOutputStream zip = new ZipOutputStream(outputStream);
    
    
    // using the openCSV library to create the csv file
    CSVWriter writer = new CSVWriter(Writer?); 
    // what writer do I use? I want to write to memory, not a file
    
    writer.writeNext(entries); 
    writer.close();
    
    // at this point should I have the csv file in memory somewhere? 
    //and then try to copy it into the zip file?
    
    int length;
    byte[] buffer = new byte[1024 * 32];    
    zip.putNextEntry(new ZipEntry(getClass() + ".csv"));
    
    // the 'in' doesn't exist yet - where am I getting the input stream from?
    while((length = in.read(buffer)) != -1)
        zip.write(buffer, 0, length);
    
    zip.closeEntry();
    zip.flush();
    
  • ant-depalma
    ant-depalma almost 11 years
    Sure but is it ok that I am never calling writer.close anywhere?
  • nadirsaghar
    nadirsaghar almost 11 years
    Yes it is. The writer is writing bytes directly to the outputstream of the servlet. If you notice you are working with the same stream throughout the code. You only need to close it once when you are done writing. We are doing that later in the code just before the catch block
  • Tan
    Tan almost 5 years
    @nadirsaghar Could you tell me from where did you get ` getContentToZIP();` method? I couldn't find it online.
  • NobesInd
    NobesInd almost 4 years
    How much time did it took to generate a zip of say 30mb?( having multiple csv inside)
  • ahiijny
    ahiijny over 2 years
    In case anyone runs into the same problem I did: I was using the javacsv library instead of opencsv for this one, and unlike opencsv, the CsvWriter class in javacsv includes a call to close() in its finalize() method, so when CsvWriter gets garbage collected, it can result in it closing the ZipOutputStream prematurely, which would cause a "Stream closed" error.