convert zip byte[] to unzip byte[] - java

I have byte[] of zip file. I have to unzip it without creating new file, and get byte[] of that unzip file.
Please help me to do that

You can use ZipInputStream and ZipOutputStream (in the package java.util.zip) to read and write from ZIP files.
If you have the data in a byte array, you can let these read from a ByteArrayInputStream or write to a ByteArrayOutputStream pointing to your input and output byte arrays.

public static List<ZipEntry> extractZipEntries(byte[] content) throws IOException {
List<ZipEntry> entries = new ArrayList<>();
ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(content));
ZipEntry entry = null;
while ((entry = zipStream.getNextEntry()) != null)
{
System.out.println( "entry: " + entry );
ZipOutputStream stream= new ZipOutputStream(new FileOutputStream(new File("F:\\ssd\\wer\\"+entry.getName())));
stream.putNextEntry(entry);
}
zipStream.close();
return entries;
}

In case you need to deflate your zipped data and you are too lazy to deal with the streams, you can use the following code:
public byte[] deflate(byte[] data) throws IOException, DataFormatException {
Inflater inflater = new Inflater();
inflater.setInput(data);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
byte[] buffer = new byte[1024];
while (!inflater.finished()) {
int count = inflater.inflate(buffer);
outputStream.write(buffer, 0, count);
}
outputStream.close();
byte[] output = outputStream.toByteArray();
return output;
}

If you have only one file in the zip, you could use the following code. If there are multiple files, just modify the if into a while.
public static byte[] toUnzippedByteArray(byte[] zippedBytes) throws IOException {
var zipInputStream = new ZipInputStream(new ByteArrayInputStream(zippedBytes));
var buff = new byte[1024];
if (zipInputStream.getNextEntry() != null) {
var outputStream = new ByteArrayOutputStream();
int l;
while ((l = zipInputStream.read(buff)) > 0) {
outputStream.write(buff, 0, l);
}
return outputStream.toByteArray();
}
return new byte[0];
}

Related

MultipartFile to .zip

How to convert a MultipartFile to .zip and then to byte?
Something like:
MultipartFile file;
ZipInputStream zip = new ZipInputStream(file.getInputStream());
Base64.getEncoder().encode(zip)
Converting MultipartFile to .zip file and retrieving its bytes:
public ResponseEntity handleFile(#RequestParam MultipartFile file) throws IOException
{
InputStream inputStream = file.getInputStream();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream);
ZipEntry zipEntry = new ZipEntry(file.getOriginalFilename());
zipOutputStream.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while((length = inputStream.read(bytes)) >= 0) {
zipOutputStream.write(bytes, 0, length);
}
zipOutputStream.close();
// Do something with the byteArrayOutputStream
System.out.println(byteArrayOutputStream.toString());
return ResponseEntity.accepted().build();
}

.zip file upload Spring

I have a Multipart file upload request. The file is a zip file- .zip format.
How do i unzip this file?
I need to populate a Hashmap with each entry's filepath and filecontent.
HashMap<filepath, filecontent>
The code I have so far:
FileInputStream fis = new FileInputStream(zipName);
ZipInputStream zis = new ZipInputStream(
new BufferedInputStream(fis));
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
int size;
byte[] buffer = new byte[2048];
FileOutputStream fos =
new FileOutputStream(entry.getName());
BufferedOutputStream bos =
new BufferedOutputStream(fos, buffer.length);
while ((size = zis.read(buffer, 0, buffer.length)) != -1) {
bos.write(buffer, 0, size);
}
bos.flush();
bos.close();
}
zis.close();
fis.close();
}
Instead of using FileOutputStream, use ByteArrayOutputStream to capture the output. Then, before executing the 'close' operation on the BAOS, use the 'toByteArray()' method on it to get the contents as a byte array (or, use 'toString()'). So, your code should look like this:
public static HashMap<String, byte[]> test(String zipName) throws Exception {
HashMap<String, byte[]> returnValue = new HashMap<>();
FileInputStream fis = new FileInputStream(zipName);
ZipInputStream zis = new ZipInputStream(
new BufferedInputStream(fis));
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
int size;
byte[] buffer = new byte[2048];
ByteArrayOutputStream baos =
new ByteArrayOutputStream();
BufferedOutputStream bos =
new BufferedOutputStream(baos, buffer.length);
while ((size = zis.read(buffer, 0, buffer.length)) != -1) {
bos.write(buffer, 0, size);
}
bos.flush();
bos.close();
returnValue.put(entry.getName(),baos.toByteArray());
}
zis.close();
fis.close();
return returnValue;
}

Zip folder is corrupted after editing content

I am trying to copy a zipped bytes array to another one using ZipOutputStream/ZipIntputStream, but it seems that the result array is not equal the original one, why is that wrong?
public static void main(String[] args) throws IOException {
File file = new File("folder.zip");
byte[] bFile = new byte[(int) file.length()];
FileInputStream fileInputStream = new FileInputStream(file);
fileInputStream.read(bFile);
fileInputStream.close();
byte[] aFile = copyZippedFileBytes(bFile);
System.out.println(Arrays.equals(aFile, bFile));
}
public static byte[] copyZippedFileBytes(byte[] arr) throws IOException {
ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(arr));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(baos);
ZipEntry entry;
while ((entry = zipStream.getNextEntry()) != null) {
zipOutputStream.putNextEntry(entry);
// assume files are small
byte[] indexFileByte = new byte[(int) entry.getSize()];
zipStream.read(indexFileByte);
zipOutputStream.write(indexFileByte);
zipOutputStream.closeEntry();
}
zipOutputStream.close();
zipStream.close();
return baos.toByteArray();
}
Solved by updated CRC of the modified entry as follow:-
CRC32 crc = new CRC32();
crc.reset();
BufferedInputStream bis = new BufferedInputStream
(new ByteArrayInputStream(data));
int bytesRead;
byte[] buffer = new byte[1024];
while ((bytesRead = bis.read(buffer)) != -1) {
crc.update(buffer, 0, bytesRead);
}
entry.setMethod(ZipEntry.STORED);
entry.setCompressedSize(data.length);
entry.setSize(data.length);
entry.setCrc(crc.getValue());

multidownload using java servlets

I want to download multiple files in single zip file using java servlet. I successfully downloaded the zip file containing multiple files (in my web page). but the problem is that files are also downloaded in my server(for ex in my jboss bin folder).
Code:
public void createZipFile(String fileNames,HttpServletResponse response,HttpServletRequest request) {
try {
ZipOutputStream outStream1 = null;
ServletOutputStream outStream=null;
FileInputStream inStream =null;
FileOutputStream fos=null;
InputStream inputStream =null;
int bytesRead = 0;
String zipFileName = "zipFileName.zip";
response.setHeader("Content-Disposition", "attachment;filename=\""+zipFileName+"\"");
response.setHeader("Pragma", "private");
response.addHeader("Cache-Control", "no-transform, max-age=0");
response.setHeader("Accept-Ranges", "bytes");
response.setContentType("application/zip");
//fileNames contains multiple file name.so i want to split and get each file
String[] fileName = fileNames.split(",");
byte[] buffer = new byte[1024];
outStream1 = new ZipOutputStream(new FileOutputStream(zipFileName));
for(int i = 0; i < fileName.length; i++) {
String filePath=audioFile.getAllFiles(fileName[i], Integer.parseInt(userId));
inputStream = new URL("************************server File location***************************").openStream();
String fileNaming = fileName[i];
String[] tempFile = fileNaming.split("\\.");
String tempFileExt=tempFile[1];
String temporaryFile=tempFile[0]+"."+tempFileExt;
fos = new FileOutputStream(temporaryFile);//here is the problem(temporary file created in my server -bin folder.but i dont want this to create)
int length = -1;
while ((length = inputStream.read(buffer)) > -1) {
fos.write(buffer, 0, length);
}
inStream = new FileInputStream(fileName[i]);
outStream1.putNextEntry(new ZipEntry(fileName[i]));
fos.close();
inputStream.close();
while ((bytesRead = inStream.read(buffer)) > 0) {
outStream1.write(buffer, 0, bytesRead);
}
}
inStream.close();
outStream1.closeEntry();
outStream1.close();
int bytesRead1 = 0;
byte[] buff = new byte[1024];
ByteArrayOutputStream bao = new ByteArrayOutputStream();
FileInputStream inStream1 =new FileInputStream(zipFileName);
while ((bytesRead1 = inStream1.read(buff)) != -1)
{
bao.write(buff, 0, bytesRead1);
}
byte[] videoBytes = bao.toByteArray();
response.setContentLength(videoBytes.length);
outStream = response.getOutputStream();
outStream.write(videoBytes);
outStream.flush();
outStream.close();
bao.close();
response.flushBuffer();
} catch (Exception ex) {
ex.printStackTrace();
}
}
For whatever reason, you're copying the files twice. Once, to the file system via inputStream and fos, and the second time to the ZipFile, via inStream and outStream1.
Seems like you can simply remove all of the code related to inputStream and fos, and you won't create the files on your filesystem.

How to return and delete file?

I want to return file (read or load) from method and then remove this file.
public File method() {
File f = loadFile();
f.delete();
return f;
}
But when I delete a file, I delete it from disk and then exists only descriptor to non-existing file on return statement. So what is the most effective way for it.
You can't keep the File handle of deleted file, rather you can keep the data in a byte array temporarily, delete the file and then return the byte array
public byte[] method() {
File f =loadFile();
FileInputStream fis = new FileInputStream(f);
byte[] data = new byte[fis.available()];
fis.read(data);
f.delete();
return data;
}
// Edit Aproach 2
FileInputStream input = new FileInputStream(f);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int bytesRead = input.read(buf);
while (bytesRead != -1) {
baos.write(buf, 0, bytesRead);
bytesRead = input.read(buf);
}
baos.flush();
byte[] bytes = baos.toByteArray();
you can construct the file data from byte array
However, my suggestion is to use IOUtils.toByteArray(InputStream input) from Jakarta commons, why do you want re write when already in plate
Assuming you want to return the file to the browser, this is how I did it :
File pdf = new File("file.pdf");
if (pdf.exists()) {
try {
InputStream inputStream = new FileInputStream(pdf);
httpServletResponse.setContentType("application/pdf");
httpServletResponse.addHeader("content-disposition", "inline;filename=file.pdf");
copy(inputStream, httpServletResponse.getOutputStream());
inputStream.close();
pdf.delete();
} catch (Exception e) {
e.printStackTrace();
}
}
private static int copy(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[512];
int count = 0;
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}

Categories

Resources