67

My application is receiving email through SMTP server. There are one or more attachments in the email and email attachment return as byte[] (using sun javamail api).

I am trying to zip the attachment files on the fly without writing them to disk first.

What is/are possible way to achieve this outcome?

8 Answers 8

167

You can use Java's java.util.zip.ZipOutputStream to create a zip file in memory. For example:

public static byte[] zipBytes(String filename, byte[] input) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ZipOutputStream zos = new ZipOutputStream(baos);
    ZipEntry entry = new ZipEntry(filename);
    entry.setSize(input.length);
    zos.putNextEntry(entry);
    zos.write(input);
    zos.closeEntry();
    zos.close();
    return baos.toByteArray();
}
Sign up to request clarification or add additional context in comments.

6 Comments

@Dave - can ZipOutputStream be sent as jax-rs output
@Deve I have the same case but I have to zip 5 file. Is there any suggestion.
@Deva you can repeat the ZipEntry-part for as manny files you like.
Thank you it worked, but I am wondering why do we need ZipOutputStream, as we are working with ByteArrayOutputStream directly ( i.e. we are returning baos)
@AshishBurnwal The ZipOutputStream is what performs the actual compression and encoding. It takes the bytes from the array and produces a compressed stream of bytes that are fed to the ByteArrayOutputStream. Then, we access and return those compressed, encoded bytes from that underlying stream to return them.
|
19

I have the same problem but i needed a many files in a zip.

 protected byte[] listBytesToZip(Map<String, byte[]> mapReporte) throws IOException {
    String extension = ".pdf";
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ZipOutputStream zos = new ZipOutputStream(baos);
    for (Entry<String, byte[]> reporte : mapReporte.entrySet()) {
        ZipEntry entry = new ZipEntry(reporte.getKey() + extension);
        entry.setSize(reporte.getValue().length);
        zos.putNextEntry(entry);
        zos.write(reporte.getValue());
    }
    zos.closeEntry();
    zos.close();
    return baos.toByteArray();
}

1 Comment

should zos.closeEntry() be inside the for loop?
1

You can create a zip file from byte array and return to ui streamedContent

public StreamedContent getXMLFile() {
        try {
            byte[] blobFromDB= null;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ZipOutputStream zos = new ZipOutputStream(baos);
            String fileName= "fileName";
            ZipEntry entry = new ZipEntry(fileName+".xml");
            entry.setSize(byteArray.length);
            zos.putNextEntry(entry);
            zos.write(byteArray);
            zos.closeEntry();
            zos.close();
            InputStream is = new ByteArrayInputStream(baos.toByteArray());
            StreamedContent zipedFile= new DefaultStreamedContent(is,   "application/zip", fileName+".zip", Charsets.UTF_8.name());
            return fileDownload;
        } catch (IOException e) {
            LOG.error("IOException e:{} ",e.getMessage());
        } catch (Exception ex) {
            LOG.error("Exception ex:{} ",ex.getMessage());
        }
}

Comments

1
   byte[] createReport() {
    try {
     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
     ZipArchiveOutputStream zipOutputStream = new 
     ZipArchiveOutputStream(byteArrayOutputStream);
     
     zipOutputStream.setMethod(ZipArchiveOutputStream.STORED);
     zipOutputStream.setEncoding(ENCODING);

     String text= "text";
     byte[] textBytes = text.getBytes(StandardCharsets.UTF_8);

     ArchiveEntry zipEntryReportObject = newStoredEntry("file.txt", textBytes);
     zipOutputStream.putArchiveEntry(zipEntryReportObject);
     zipOutputStream.write(textBytes);

     zipOutputStream.closeArchiveEntry();
     zipOutputStream.close();
    
     return byteArrayOutputStream.toByteArray();
     } catch (IOException e) {
       return null;
    }

and

ArchiveEntry newStoredEntry(String name, byte[] data) {
    ZipArchiveEntry zipEntry = new ZipArchiveEntry(name);
    zipEntry.setSize(data.length);
    zipEntry.setCompressedSize(zipEntry.getSize());
    CRC32 crc32 = new CRC32();
    crc32.update(data);
    zipEntry.setCrc(crc32.getValue());
    return zipEntry;
  }

1 Comment

Please specify that your code requires an external library like Apache Commons Compress
0

Maybe the java.util.zip package might help you

Since you're asking about how to convert from byte array I think (not tested) you can use the ByteArrayInputStream method

int     read(byte[] b, int off, int len)
          Reads up to len bytes of data into an array of bytes from this input stream.

that you will feed to

ZipInputStream  This class implements an input stream filter for reading files in the ZIP file format.

Comments

0

You have to use a ZipOutputStream for that.

http://java.sun.com/javase/6/docs/api/java/util/zip/ZipOutputStream.html

Comments

0
ByteArrayInputStream bais = new ByteArrayInputStream(retByte);
                
ZipInputStream zis = new ZipInputStream(bais);
           
zis.getNextEntry();

Scanner sc = new Scanner(zis);
while (sc.hasNextLine()) {
    System.out.println("-->:" +sc.nextLine());
}

zis.closeEntry();
zis.close();

Comments

0
public static void createZip(byte[] data) throws ZipException {
    ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(data));
    ZipParameters parameters = new ZipParameters();
    parameters.setFileNameInZip("bank.zip");
    new ZipFile("F:\\ssd\\bank.zip").addStream(new ByteArrayInputStream(data), parameters);
}

1 Comment

use <dependency> <groupId>net.lingala.zip4j</groupId> <artifactId>zip4j</artifactId> <version>2.6.4</version> </dependency>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.