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?
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();
}
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();
}
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());
}
}
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;
}
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.
You have to use a ZipOutputStream for that.
http://java.sun.com/javase/6/docs/api/java/util/zip/ZipOutputStream.html
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();
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);
}
Related
I have a file in the server, I want to create three java APIs, which will do the below three operations in dependently.
Get the file size
Move a file with different file name to a different server location
Zip the file
In my existing code we are executing Linux commands to perform those operations, unfortunately, Linux commands are not getting executed, this is due to some server/set up issue, so I am forced to use Java commands.(We use JDK 1.6)
I am not a Java developer. I have gone through some of the previously answered questions, but they are not explaining about file in server path. Any help is much appreciated.
To get the file size in bytes:
File file = new File("filename.txt");
long fileSize = file.length();
To move a file you must first copy it and then delete the original:
InputStream inStream = null;
OutputStream outStream = null;
try {
File fromFile = new File("startfolder\\filename.txt");
File toFile = new File("endfolder\\filename.txt");
inStream = new FileInputStream(fromFile);
outStream = new FileOutputStream(toFile);
byte[] buffer = new byte[1024];
int length;
while ((length = inStream.read(buffer)) > 0){
outStream.write(buffer, 0, length);
}
inStream.close();
outStream.close();
fromFile.delete();
} catch(IOException e) {
e.printStackTrace();
}
To zip a file:
byte[] buffer = new byte[1024];
try {
FileInputStream fileToZip = new FileInputStream("filename.txt");
FileOutputStream fileOutputStream = new FileOutputStream("filename.zip");
ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream);
ZipEntry zipEntry= new ZipEntry("filename.txt");
zipOutputStream.putNextEntry(zipEntry);
int len;
while ((len = fileToZip.read(buffer)) > 0) {
zipOutputStream.write(buffer, 0, len);
}
fileToZip.close();
zipOutputStream.closeEntry();
zipOutputStream.close();
} catch(IOException e) {
e.printStackTrace();
}
Hi i am just wondering is it possible to set the deflater used in gzip output stream to use HUFFMAN_ONLY, i have it working with my own deflate method.
public static byte[] deflate(byte[] data) throws IOException {
Deflater deflater = new Deflater();
deflater.setInput(data);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
deflater.finish();
deflater.setLevel(Deflater.BEST_COMPRESSION); //*****THESE 2 LINES HERE
deflater.setStrategy(Deflater.HUFFMAN_ONLY); // *******
byte[] buffer = new byte[1024];
while (!deflater.finished()) {
int count = deflater.deflate(buffer); // returns the generated code... index
outputStream.write(buffer, 0, count);
}
outputStream.close();
byte[] output = outputStream.toByteArray();
return output;
}
so basically i want to know how to set the deflater used in my gzip method to the same as the deflater above when i use the lines:
deflater.setLevel(Deflater.BEST_COMPRESSION);
deflater.setStrategy(Deflater.HUFFMAN_ONLY);
this is my gzip method:
//GZIP Compression method
public static byte[] compress(String data) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length());
GZIPOutputStream gzip = new GZIPOutputStream(bos);
gzip.write(data.getBytes());
gzip.close();
byte[] compressed = bos.toByteArray();
bos.close();
return compressed;
}
No, but you can just use Deflater with nowrap set to true, and write your own gzip header and trailer.
I have hosted my java web application in a unix server the files are generated in a context path,zipped and downloaded to the client. My code is working once I have hosted the Application in a Windows server but not in Centos .. What could be the issue?
My zip Method:
private byte[] zipFiles(File directory, String[] files) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
byte bytes[] = new byte[2048];
for (String fileName : files) {
FileInputStream fis = new FileInputStream(directory.getPath()
+ crbServlet.FILE_SEPARATOR + fileName);
BufferedInputStream bis = new BufferedInputStream(fis);
zos.putNextEntry(new ZipEntry(fileName));
int bytesRead;
while ((bytesRead = bis.read(bytes)) != -1) {
zos.write(bytes, 0, bytesRead);
}
zos.closeEntry();
bis.close();
fis.close();
}
zos.flush();
baos.flush();
zos.close();
baos.close();
return baos.toByteArray();
}
My servlet Extract:
String[] files = f.list();
if (files != null && files.length > 0) {
byte[] zip = zipFiles(f, files);
ServletOutputStream sos = response.getOutputStream();
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=\"datafiles" + dt.getCurrentDate() + ".zip\"");
sos.write(zip);
sos.flush();
}
What I am getting downloaded on the client side is a do file that has junk character. What is the issue here?
does someone have an idea why this code to create a gzipped string is not working? CLI gzip on a Mac can't open the resulting file: "Not in gz format".
Please note: I need the string, not the file. Creating the gzipped file directly works, so does writing the JSON without zipping it.
The file writing in this example is just for testing purposes.
public someMethod {
String gzippedString = this.gzippedString(finalJSONObject.toJSONString());
OutputStream outputStream = new FileOutputStream(new File(this.jsonOutputPath + "/myfile.gz"));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
writer.append(gzippedString);
writer.close();
}
private String gzippedString(String inputString) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
gzipOutputStream.write(inputString.getBytes());
gzipOutputStream.close();
outputStream.close();
String gzippedString = outputStream.toString();
return gzippedString;
}
EDIT:
chrylis showed me the way:
public void someMethod() {
byte[] byteArray = this.gzippedByteArray(finalJSONObject.toJSONString());
FileOutputStream out = new FileOutputStream(this.jsonOutputPath + "/myfile.gz");
out.write(byteArray);
out.close();
}
private byte[] gzippedByteArray(String inputString) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
gzipOutputStream.write(inputString.getBytes());
gzipOutputStream.close();
outputStream.close();
byte[] gzippedByteArray = outputStream.toByteArray();
return gzippedByteArray;
}
This results in a working gzipped JSON.
Thanks a lot!
You're round-tripping binary data through a String, which has a character encoding and other such mangling. Use the byte[] directly instead.
I am facing this issue while unzipping a file and writing it in to another file. Here is the code. Can any one please let me know what changes are required.
I get this exception on the line with while ((len = zis.read(buffer)) > 0)
private FileItem readZippedFileRequest(HttpServletRequest request,Part part, String fileName) {
FileItem fileItem = null;
byte[] buffer = new byte[1024];
InputStream inputStream = part.getInputStream();
ZipInputStream zis = new ZipInputStream(inputStream);
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
ByteArrayOutputStream fos = new ByteArrayOutputStream();
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
InputStream myByteArray = new ByteArrayInputStream(fos.toByteArray());
fileItem = createCSVFile(myByteArray, fileName,ImportExportConstant.FILE_TYPE_EXCEL);
}
return fileItem;
}
There's nothing wrong with your code. There is something wrong with the file, as the message says. Are you sure it is zipped, and not GZipped for example? It would be more usual for a part to be GZipped. Try a GZIPInputStream.
NB there's no need for the ByteArrayInputStream. It's a complete waste of time and space. Just pass the zip/gzip input stream directly to your createCSVFile() method.
I have this error too and I searched a little bit... I've read that there must be zis.closeEntry(); before len = zis.read(buffer) but I tried it and then the error appears at zis.closeEntry();
I asked google and here is the answer:
!Answer!
I tried and wrote a little bit, then I switched the throws IOException in a try/catch-block and now there is all right.
The Exception is a well known bug. You have to put all in a try/catch-block and do nothing in the catch.
private FileItem readZippedFileRequest(HttpServletRequest request,Part part, String fileName) {
FileItem fileItem = null;
byte[] buffer = new byte[1024];
try{
InputStream inputStream = part.getInputStream();
ZipInputStream zis = new ZipInputStream(inputStream);
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
ByteArrayOutputStream fos = new ByteArrayOutputStream();
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
InputStream myByteArray = new ByteArrayInputStream(fos.toByteArray());
fileItem = createCSVFile(myByteArray, fileName,ImportExportConstant.FILE_TYPE_EXCEL);
}
}catch(IOException ex){
//Do nothing here
}
return fileItem;
}