Unzip in memory for google App Engine Java - java

I would like to unzip a file uploaded to a servlet, and store all decompressed files to the DataStore as byte[]. Since there is no file system in GAE, I have to put everything in memory. Suppose I have byte[] allzipdata to store the original zip file data. How do I unzip the file and especially how to get inputstream from each zipentry which are in memory?
ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(allzipdata));
ZipEntry ze = zis.getNextEntry();
while(ze!=null){
}
So what's in the while loop?
Also, if I upload a file, I know the contentType using item.getContentType(); in which item is a FileItemStream. So for a zipentry, is there a way to know the contentType?

To read image data from the ZipInputStream I'd recommend to use the Apache Commons-IO library. It converts the ZIP entry of the input stream to a byte array:
ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(allzipdata));
ZipEntry ze = null;
while ((ze = zis.getNextEntry()) != null) {
// write your code to use zip entry e.g. below:
String filename = ze.getName();
System.out.println("File Name of Entry file="+fileName);
byte[] data = IOUtils.toByteArray(zis);
// now work with the image `data`
}

Related

How can I read zip file without saving to the disk with Spring Boot?

There are already many similar questions and tutorials available about this topic still I didn't found what I wanted to do.
I want to make an API, though which I can upload the zip file, that zip is containing xml files I am reading those files and sending the content as response.
The only problem here is currently I am storing the file inside of my project directory, but I don't want that I want to read the file directly without storing it in an directory.
So basically user will hit my API, upload the file and in response he will get the data present inside of files in that zip.
My Code:
#RequestMapping(value ="/upload", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<Object> uploadFile(#RequestParam("file")MultipartFile file) throws IOException {
System.out.println(file.getOriginalFilename());
File converFile = new File("src/main/"+file.getOriginalFilename());
converFile.createNewFile();
FileOutputStream fout = new FileOutputStream(converFile);
fout.write(file.getBytes());
//unzipping file and reading data;
String zipFileName = "src/main/"+file.getOriginalFilename();
List<String> str = new ArrayList<String>();
byte[] buffer = new byte[1024];
ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFileName));
ZipEntry zipEntry;
int read;
while ((zipEntry = zis.getNextEntry())!= null) {
while ((read = zis.read(buffer, 0, 1024)) >= 0) {
str.add(new String(buffer,0,read));
}
}
while (zipEntry != null){
zipEntry = zis.getNextEntry();
}
zis.closeEntry();
zis.close();
System.out.println("Unzip complete");
System.out.println("--------------------------------");
System.out.println("List"+ str);
fout.close();
return new ResponseEntity<>(str, HttpStatus.OK);
}
This code is working fine uploading file saving it in project directory (src/main) and reading file data and giving the data as response.
How can I eliminate the saving part and do all these in code only.
You can use ByteArrayInputStream instead of FileInputStream, like this:
ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(file.getBytes()));

Save bytes to a pdf file and zip it

I am trying to save bytes[] data in a pdf and zip it up. Everytime I try, I get a blank pdf. Below is the code. Can anyone guide me what am I doing wrong?
byte[] decodedBytes = Base64.decodeBase64(contents);
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream("c:\\output\\asdwd.zip")));
//now create the entry in zip file
ZipEntry entry = new ZipEntry("asd.pdf");
zos.putNextEntry(entry);
zos.write(decodedBytes);
zos.close();
This is what I am following
To obtain the actual PDF document, you must decode the Base64-encoded string, save it as a binary file with a “.zip” extension, and then extract the PDF file from the ZIP file.
You don’t actually need to create a zip file. The instructions are telling you that the base64 data represents a zipped PDF, so you can unzip it in code and write the PDF file itself:
Path pdfFile = Files.createTempFile(null, ".pdf");
try (ZipInputStream zip = new ZipInputStream(
new ByteArrayInputStream(
Base64.getDecoder().decode(contents)))) {
ZipEntry entry;
while ((entry = zip.getNextEntry()) != null) {
String name = entry.getName();
if (name.endsWith(".pdf") || name.endsWith(".PDF")) {
Files.copy(zip, pdfFile, StandardCopyOption.REPLACE_EXISTING);
break;
}
}
}

InputStream of each entry in a zip passed as a byte array in Java

I need the InputStream for each entry of my zip (contains various files and folders) passed as a byte array.
This is what I have so far:
private void accessEachFileInZip (byte[] zipAsByteArray) throws IOException{
ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(zipAsByteArray));
ZipEntry entry = null;
while ((entry = zipStream.getNextEntry()) != null) {
ZipEntry currentEntry = entry;
InputStream inputStreamOfCurrentEntry = ???
zipStream.closeEntry();
}
zipStream.close();
}
There is a simple way doing this with a ZipFile instance by just calling getInputStream("EnrtryImLookingFor") like in this example:
ZipFile zipFile = new ZipFile("d:\\data\\myzipfile.zip");
ZipEntry zipEntry = zipFile.getEntry("fileName.txt");
InputStream inputStream = zipFile.getInputStream(zipEntry);
Since I can't create an instance that easily, I'm looking for an other way.
You are close to.
ZipInputStream.getNextEntry() does two things : it returns the next ZIP file entry but it also positions the current stream at the beginning of the current entry.
Reads the next ZIP file entry and positions the stream at the
beginning of the entry data.
So just invoke getNextEntry() and then you can use the ZipInputStream object which the read() method will read the content of the current entry.
you could write something like :
private void accessEachFileInZip (byte[] zipAsByteArray) throws IOException{
ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(zipAsByteArray));
while ((entry = zipStream.getNextEntry()) != null) {
// The zipStream state refers now to the stream of the current entry
...
}
zipStream.close();
}

How to read content of the Zipped file without extracting in java

I have file with names like ex.zip. In this example, the Zip file contains only one file with the same name(ie. `ex.txt'), which is quite large. I don't want to extract the zip file every time.Hence I need to read the content of the file(ex.txt) without extracting the zip file. I tried some code like below But i can only read the name of the file in the variable.
How do I read the content of the file and stores it in the variable?
Thank you in Advance
fis=new FileInputStream("C:/Documents and Settings/satheesh/Desktop/ex.zip");
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
ZipEntry entry;
while((entry = zis.getNextEntry()) != null) {
i=i+1;
System.out.println(entry);
System.out.println(i);
//read from zis until available
}
Your idea is to read the zip file as it is into a byte array and store it in a variable.
Later when you need the zip you extract it on demand, saving memory:
First read the content of the Zip file in a byte array zipFileBytes
If you have Java 1.7:
Path path = Paths.get("path/to/file");
byte[] zipFileBytes= Files.readAllBytes(path);
otherwise use Appache.commons lib
byte[] zipFileBytes;
zipFileBytes = IOUtils.toByteArray(InputStream input);
Now your Zip file is stored in a variable zipFileBytes, still in compressed form.
Then when you need to extract something use
ByteArrayInputStream bis = new ByteArrayInputStream(zipFileBytes));
ZipInputStream zis = new ZipInputStream(bis);
Try this:
String zipFile = "ex.zip";
try (ZipFile zip = new ZipFile(zipFile)) {
int i = 0;
for (Enumeration<? extends ZipEntry> e = zip.entries(); e.hasMoreElements(); ) {
ZipEntry entry = (ZipEntry) e.nextElement();
System.out.println(entry);
System.out.println(i);
InputStream in = zip.getInputStream(entry);
}
}
For example, if the file contains text, and you want to print it as a String, you can read the InputStream like this: How do I read / convert an InputStream into a String in Java?
I think that in your case the fact that a zipfile is a container that can hold many files (and thus forces you to navigate to the right contained file each time you open it) seriously complicates things, as you state that each zipfile only contains one textfile. Maybe it's a lot easier to just gzip the text file (gzip is not a container, just a compressed version of your data). And it's very simple to use:
GZIPInputStream gis = new GZIPInputStream(new FileInputStream("file.txt.gz"));
// and a BufferedReader on top to comfortably read the file
BufferedReader in = new BufferedReader(new InputStreamReader(gis) );
Producing them is equally simple:
GZIPOutputStream gos = new GZIPOutputStream(new FileOutputStream("file.txt.gz"));

Spring: how to parse uploaded zip file?

I uploaded my zip archive to the server and want to open .txt and .jpg files in it. I successfully get my archive in my Controller and get the name of each file via ZipEntry. Now I want to open it but for this I should get a full path to my file.
I haven't found how I can do that. Could you suggest some approach how to do that ?
Update
I try to use example have been suggested below but I am not be able open the file
ZipFile zFile = new ZipFile("trainingDefaultApp.zip");
I have got the FileNotFoundException
So I return to my start point. I have upload form in Java Spring application. In controller I had got a zip archive as byte[]
#RequestMapping(method = RequestMethod.POST)
public String create(UploadItem uploadItem, BindingResult bindingResult){
try {
byte[] zip = uploadItem.getFileData().getBytes();
saveFile(zip);
Then I had got each ZipEntry
InputStream is = new ByteArrayInputStream(zip);
ZipInputStream zis = new ZipInputStream(is);
ZipEntry entry = null;
while ((entry = zis.getNextEntry()) != null) {
String entryName = entry.getName();
if (entryName.equals("readme.txt")) {
ZipFile zip = new ZipFile(entry.getName()); // here I had got an exception
According to docs I did all right but as for me it is strange to pass the file name only and suspect that you successfully will open the file
I resolve my uissue. The solution is work directly with ZipInputStream. Here the code:
private void saveFile(byte[] zip, String name, String description) throws IOException {
InputStream is = new ByteArrayInputStream(zip);
ZipInputStream zis = new ZipInputStream(is);
Application app = new Application();
ZipEntry entry = null;
while ((entry = zis.getNextEntry()) != null) {
String entryName = entry.getName();
if (entryName.equals("readme.txt")) {
new Scanner(zis); //!!!
//...
zis.closeEntry();
zipFile.getInputStream(ZipEntry entry) will return you the inputstream for the specific entry.
Check out the javadocs for ZipFile.getInputStream() - http://docs.oracle.com/javase/6/docs/api/java/util/zip/ZipFile.html#getInputStream(java.util.zip.ZipEntry).
Update:
I misread your question. For using the ZipInputStream, there is sample code on Oracle's website (http://java.sun.com/developer/technicalArticles/Programming/compression/) that shows you how to read from the stream. See the first code sample: Code
Sample 1: UnZip.java.
Copying here, it is reading from the entry and writing it directly to a file, but you could replace that with whatever logic you need:
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
ZipEntry entry;
while((entry = zis.getNextEntry()) != null) {
System.out.println("Extracting: " +entry);
int count;
byte data[] = new byte[BUFFER];
// write the files to the disk
FileOutputStream fos = new FileOutputStream(entry.getName());
dest = new
BufferedOutputStream(fos, BUFFER);
while ((count = zis.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, count);
}
}

Categories

Resources