Unzip through CommonsMultipartFile - java

I have a app (spring-mvc) and I want to unzip a file but I want to catch the files that it is inside and to be able to work with theirs without save zip file neither files that it has (zip file).
Something like this
...
ZipFile zipFile = new ZipFile("file.zip");
Enumeration<?> enu = zipFile.entries();
while (enu.hasMoreElements()) {
ZipEntry zipEntry = (ZipEntry) enu.nextElement();
InputStream is = zipFile.getInputStream(zipEntry);
}
...
But I have zip file ("file.zip") through of CommonsMultipartFile (spring-mvc) and no of the disk
How can I do this?
Thanks.

If you don't want to save zipfile contents to a temporary file, you can read it by using ZipInputStream.
ZipInputStream zis = new ZipInputStream(multipartFile.getInputStream());
ZipEntry ze;
while ((ze = zis.getNextEntry()) != null) {
// process entry
}

Related

How to get an InputStream representing one file in a ZipInputStream

I have the following situation:
I am getting a Zip File sent over the network in the Form of a Byte Array. I don't want to save that file locally, but instead target an individual file in that archive and import it into my solution as an InputStream.
Thus far, I have managed to get to the point where I can identify the correct ZipEntry. However, from here all the Zip-tutorials continue by reading the entry by its file name, which naturally does not work in my case since the zip file does not exist locally.
private void InputStream getReqifInputStreamFrom(byte[] reqifzFileBytes){
ByteArrayInputStream inputStream = new ByteArrayInputStream(reqifzFileBytes);
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
ZipEntry zipEntry = zipInputStream.getNextEntry();
while (zipEntry != null) {
String fileName = zipEntry.getName();
if (fileName.endsWith(REQIF_FILE_SUFFIX)) {
return ???;
}
zipEntry = zipInputStream.getNextEntry();
}
}
So, what can I do at that point to return an InputStream that represents exactly the one file that the ZipEntry represents at that point? I have considered just returning the zipInputStream, but since I don't know exactly how that one works I'm afraid that doing so would also include all files that are still in the stream after that file to be returned as well.
You're virtually there. Try
private InputStream getReqifInputStreamFrom(byte[] reqifzFileBytes) throws IOException {
InputStream result = null;
ByteArrayInputStream inputStream = new ByteArrayInputStream(reqifzFileBytes);
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
ZipEntry zipEntry = zipInputStream.getNextEntry();
while (zipEntry != null) {
String fileName = zipEntry.getName();
if (fileName.endsWith(REQIF_FILE_SUFFIX)) {
result = zipInputStream;
break;
}
zipEntry = zipInputStream.getNextEntry();
}
return result;
}

How to convert javax.mail.BodyPart with content type "Application/zip" to list of java.io.File objects?

I have BodyPart object from email which is a .zip archive. And i need to extract all files from it, but can't find any solution.
I tried this:
List<File> files = new ArrayList<>();
try (ZipInputStream zis = (ZipInputStream)bodyPart.getInputStream()) {
ZipEntry zipEntry;
while ((zipEntry = zis.getNextEntry()) != null) {
LOG.info("Unzipping: {}", zipEntry.getName());
File file = new File(zipEntry.getName());
files.add(file);
}
}
return files;
But it throws exception on casting bodyPart.getInputStream to ZipInputStream'.
Is there another way to convert .zip BodyPart to list of archive's content?

ZipEntry to File

Is there a direct way to unpack a java.util.zip.ZipEntry to a File?
I want to specify a location (like "C:\temp\myfile.java") and unpack the Entry to that location.
There is some code with streams on the net, but I would prefer a tested library function.
Use ZipFile class
ZipFile zf = new ZipFile("zipfile");
Get entry
ZipEntry e = zf.getEntry("name");
Get inpustream
InputStream is = zf.getInputStream(e);
Save bytes
Files.copy(is, Paths.get("C:\\temp\\myfile.java"));
Use the below code to extract the "zip file" into File's then added in the list using ZipEntry. Hopefully, this will help you.
private List<File> unzip(Resource resource) {
List<File> files = new ArrayList<>();
try {
ZipInputStream zin = new ZipInputStream(resource.getInputStream());
ZipEntry entry = null;
while((entry = zin.getNextEntry()) != null) {
File file = new File(entry.getName());
FileOutputStream os = new FileOutputStream(file);
for (int c = zin.read(); c != -1; c = zin.read()) {
os.write(c);
}
os.close();
files.add(file);
}
} catch (IOException e) {
log.error("Error while extract the zip: "+e);
}
return files;
}
Use ZipInputStream to move to the desired ZipEntry by iterating using the getNextEntry() method. Then use the ZipInputStream.read(...) method to read the bytes for the current ZipEntry. Output those bytes to a FileOutputStream pointing to a file of your choice.

WinZip is unable to open zipped file prepared using Apache commons compress ApI

I have a scenario to zip some files and folders (with sub-folders). I was able to achieve this perfectly using Apache Commons Compress library, with help from this post. I have an application which uses java.util.zip library to unzip the file. This utility is not able to read the Apache Commons Compress zipped folder, the very first ZipEntry is null.
However when the zipped file is prepared using WinZip, the utility has no problem in unzipping it.
I also tried to unzip the compression zip file using WinZip, it gives an error - Unable to open the local header for "filename".
Any idea how to add the local header files? I checked the source code for ZipArchiveOutputStream, it does writetolocalheaderFile.
Any pointers to this issue?
Unzip code is below:
{
File destDir = new File(destDirectory);
ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFilePath));
ZipEntry entry = zipIn.getNextEntry();
// iterates over entries in the zip file
while (entry != null) {
String filePath = destDirectory + File.separator + entry.getName();
if (!entry.isDirectory()) {
// if the entry is a file, extracts it
extractFile(zipIn, filePath, CurrentSize, totalSize);
} else {
// if the entry is a directory, make the directory
File dir = new File(filePath);
dir.mkdir();
}
zipIn.closeEntry();
entry = zipIn.getNextEntry();
}
zipIn.close();
}
However I am able to see that there are entries available in zip file through other ways, but unfortunately cannot include new code in the utility.
Code snippet:
ZipFile zipFile = new ZipFile(new File(zipFilePath));
Enumeration entries = zipFile.entries();
while(entries.hasMoreElements()) {
ZipEntry ze = (ZipEntry) entries.nextElement();
System.out.println(ze.getName());
if(!ze.isDirectory())
System.out.println("Is not a directory");
}

How to read a war/jar file which does not have manifest

I have a war file which does not contains manifest not even META-INF folder. Now my problem is that I wrote a code which was working fine with normal war files containing manifests. Now I am required to read a war file which does not contain manifest.
When I check
while ((ze = zis.getNextEntry()) != null)
This condition is just skipped. Is there any API which treats it just as a normal zip file or is there any workaround.
I have tried with JarEntry as well as ZipEntry. Here is a small snippet that should be explanatory.
try {
FileInputStream fis = new FileInputStream(applicationPack);
ZipArchiveInputStream zis = new ZipArchiveInputStream(fis);
ArchiveEntry ze = null;
File applicationPackConfiguration;
while ((ze = zis.getNextEntry()) != null) {
// do someting
}
What can be done ?
You can simply list contents with ZipFile class:
try {
// Open the ZIP file
ZipFile zf = new ZipFile("filename.zip");
// Enumerate each entry
for (Enumeration entries = zf.entries(); entries.hasMoreElements();) {
// Get the entry name
String zipEntryName = ((ZipEntry)entries.nextElement()).getName();
}
} catch (IOException e) {
}
Example taken from here. Another example for retrieving the file from zip.
Update:
Code above indeed has problems with zip files that contain only directory as a top-level element.
This code works (tested):
try {
// Open the ZIP file
FileInputStream fis = new FileInputStream(new File("/your.war"));
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
ZipEntry entry = null;
while ((entry = zis.getNextEntry()) != null)
// Get the entry name
System.out.println(entry.getName());
} catch (IOException e) {
}
You can use classes from java.util.zip package. Just replace ZipArchiveInputStream with ZipInputStream and ArchiveEntry with ZipEntry:
FileInputStream fis = new FileInputStream(new File("/path/to/your.war"));
ZipInputStream zis = new ZipInputStream(fis);
ZipEntry ze = null;
while ((ze = zis.getNextEntry()) != null) {
System.out.println(ze.getName());
}

Categories