FTP zip file extract Error - java

I am trying to extract zip files from the server(A zip file is in the server.so I am trying to extract that through the FTP) and I am using this code,
byte[] buf = new byte[1024];
ZipInputStream zinstream = new ZipInputStream(Home.ftpClient.retrieveFileStream("HO2BR.br.3162675983055490721.zync"));
ZipEntry zentry = zinstream.getNextEntry();
System.out.println("Name of current Zip Entry : " + zentry + "\n");
while (zentry != null) {
String entryName = zentry.getName();
System.out.println("Name of Zip Entry : " + entryName);
FileOutputStream outstream = new FileOutputStream(entryName);
int n;
while ((n = zinstream.read(buf, 0, 1024)) > -1) {
outstream.write(buf, 0, n);
}
System.out.println("Successfully Extracted File Name : " + entryName);
outstream.close();
zinstream.closeEntry();
zentry = zinstream.getNextEntry();
}
zinstream.close();
}
ZipInputStream(Home.ftpClient.retrieveFileStream("HO2BR.br.3162675983055490721.zync"));
to Input stream assign the FTPClient 's retrieveFileStream
while executing the program this error is occurred
java.util.zip.ZipException: invalid distance too far back
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:164)
How can I solve this exception?

Most likely the ftpClient.retrieveFileStream does not support seeking. The Zip "table of contents" entries occur at the very end of the file. So, "opening" the first item requires the ability to back up to the start of the file to read that item.
You'll need to download the zip file to a local file, then extract the contents from there.

The solution is to change the transfer mode from ASCII to BINARY

Related

Unable to open S3 zip file downloaded using spring-boot

My AWS S3 contains some files and I want to download those files through my application as a zip file. I'm able to download the zip file successfully but while the file I'm getting an error Unexpected end of archive and also the CSV file size is 0 inside the zip.
I did dig a lot but not able to understand the exact solutions.
Here's the code:
String zipFileName = "MyZipFile.zip";
String fileName = "test.csv";
filePath = new String(Base64.getDecoder().decode(filePath));
System.out.println("file:" + filePath);
// get file from S3
S3Object s3Obj = awsClient.downloadFile(filePath);
byte[] s3Bytes = s3Obj.getObjectContent().readAllBytes();
// create zip
ByteArrayOutputStream byteArrOutputStream = new ByteArrayOutputStream(s3Bytes.length);
ZipOutputStream zipOutStream = new ZipOutputStream(byteArrOutputStream);
ZipEntry zip = new ZipEntry(fileName);
zipOutStream.putNextEntry(zip);
zipOutStream.write(s3Bytes, 0, s3Bytes.length);
byte[] streamBytes = byteArrOutputStream.toByteArray();
// close streams
zipOutStream.closeEntry();
zipOutStream.close();
closeQuietly(byteArrOutputStream);
// prepare download
System.out.println("streamBytes:" + streamBytes + " len:" + streamBytes.length);
System.out.println("s3Bytes:" + s3Bytes + " len:" + s3Bytes.length);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentLength(streamBytes.length);
headers.setContentDispositionFormData("attachment", zipFileName);
I think you should close your zip output stream to have everything written to the underlying byte array stream before you extract the byte array... Ie reorder the lines to:
// close streams
zipOutStream.closeEntry();
zipOutStream.close();
byte[] streamBytes = byteArrOutputStream.toByteArray();
closeQuietly(byteArrOutputStream);

Add suffix to filename if file already exist instead of overwriting it

I'm saving an uploaded file as below:
UploadItem item = event.getUploadItem();
File dir = new File("D:/FileUpload");
if (!dir.exists()) {
dir.mkdir();
}
File bfile = new File("D:/FileUpload" + "/" + item.getFileName());
OutputStream outStream = new FileOutputStream(bfile);
outStream.write(item.getData());
outStream.close();
But my question is when upload once file same old file in folder D:/FileUpload. In above function it will delete old file. Example first time, i upload file : test.doc (old file). Then i upload another file with same name : test.doc (new file). At folder FileUpload will has one file is test.doc (new file). I want function will process similar in window OS is : new file will be test (2).doc. How can i process it ? And all cases : D:/FileUpload have many file : test.doc, test (1).doc, test (2).doc, test (a).doc,...... I think we just check with format ....(int).doc. That new file will be :
test (3).doc (ignore test(a).doc)
Maybe you're looking for something like this? I list the files in your directory, compare the names of each to the name of your file. If the names match, increment a count. Then, when you come to create your file, include the count in its name.
UploadItem item = event.getUploadItem();
File dir = new File("D:/FileUpload");
if (!dir.exists()) {
dir.mkdir();
}
String [] files = dir.list();
int count = 0;
for(String file : files) {
if (file.startsWith(item.getFileName()) {
count++;
}
}
File bfile = new File("D:/FileUpload" + "/" + item.getFileName() + "(" + count + ")");
OutputStream outStream = new FileOutputStream(bfile);
outStream.write(item.getData());
outStream.close();

Unzipping file Zip Exception: invalid entry size (expected 193144 but got 193138 bytes)

I am trying to unzip a file (retrieved from an FTP server):
ZipInputStream zis = new ZipInputStream(
new FileInputStream(zipFile));
ZipEntry ze = zis.getNextEntry();
while (ze != null) {
String fileName = ze.getName();
File newFile = new File(outputFileName+outputFolder + File.separator + fileName);
System.out.println("file unzip : " + newFile.getAbsoluteFile());
FileOutputStream fos = new FileOutputStream(newFile);
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
sendFile = newFile;
ze = zis.getNextEntry();
}
zis.closeEntry();
zis.close();
System.out.println("Done");
I have only one text file in the .zip file. This code works fine on my local windows machine. However, when deployed onto ubuntu server, it throws the following exception..
java.util.zip.ZipException: invalid entry size (expected 193144 but got 193138 bytes)
at java.util.zip.ZipInputStream.readEnd(ZipInputStream.java:386)
at java.util.zip.ZipInputStream.read(ZipInputStream.java:156)
at java.io.FilterInputStream.read(FilterInputStream.java:90)
at com.empress.Xsync.updater.ClientConfiguration.unZipFile(ClientConfiguration.java:246)
I have manually unzipped it..works fine.
Original .txt file size is 193144 bytes.
It looks like your zip file has been corrupted in the process of transferring it to the Ubuntu machine. Try unzipping the same file from the command line on the Ubuntu machine to see if it also reports problems.
If I was to make a random guess, it would be that you transferred the ZIP file via FTP and used 'ascii' mode instead of 'binary' mode. (FTP could have converted '\r\n' to '\n' six times ...)

Error on Extracting a File in zip archive in Java

I'm extracting a file from a zip archive using this code (omitting all the catch statements and other initialization statements):
zipInputStream = new ZipInputStream(new FileInputStream(file));
zipFile = new ZipFile(file);
for (Enumeration<?> em = zipFile.entries(); em.hasMoreElements();) {
String extractedFileName = em.nextElement().toString();
ZipEntry outerZipEntry = zipInputStream.getNextEntry();
if (outerZipEntry.getName().contains(searchString)) {
extractedFile = new File(outputDir + outerZipEntry.getName());
out = new FileOutputStream(outputDir + extractedFileName);
byte[] buf = new byte[1024];
int len;
while ((len = zipInputStream.read(buf)) > 0) {
out.write(buf, 0, len);
}
break;
}
}
This code works fine when extracting a file in say, /archive.zip/file_i_need.txt.
But when I'm trying to extract a file from /archive.zip/folder1/file_i_need.txt, I get an exception java.lang.NullPointerException when I try to use readLine() to read the file in:
String line = null ;
BufferedReader input = new BufferedReader(newFileReader(extractedFile)) ;
while( (line = input.readLine() ) != null ) {
...
}
I've tested it on both cases and it seems like this code will not work when the file is inside a folder because the extractedFileName is 'folder/file_i_need.txt' compared to just 'file_i_need.txt'.
Any suggestions you can recommend?
Thanks!
extractedFile = new File(outputDir + outerZipEntry.getName());
The problem is you're not taking into account that the entries name may contain a path element, which you are not creating, you simply try an write to the file. Why this doesn't produce an error, I'm not sure.
Are you writing these files on Windows?? This would create a file like folder1/file_i_need.txt on the file system, which is probably invalid at some level :P
Try extracting the file name from the ZipEntry
String name = outerZipEntry.getName();
name = name.substring(name.lastIndexOf("/") + 1);
Obviously, check that name actually contains a "/" first ;)
UPDATE
While I'm at it, this looks wrong
extractedFile = new File(outputDir + outerZipEntry.getName());
out = new FileOutputStream(outputDir + extractedFileName);
Basically your saying outputDir + outerZipEntry.getName() + (outputDir + outerZipEntry.getName())
UPDATE
I tested this on Windows and I get a FileNotFoundException when I try and write the file to a path that does not exist
I also tested it on my MaC and I get a FileNotFoundException
I don't know what your error handling is doing, but it's doing it wrong.
I think your issue is that you can't open a FileOutputStream on line out = new FileOutputStream(outputDir + extractedFileName);. You can't open a stream because if extractedFileName is folder1/file_i_need.txt and outputDir is, for example, C:/OutputDir then you're trying to open a stream on C:/OutputDirfolder1/file_i_need.txt. Such directory doesn't exist and out becomes null.
The post I was referring to in my comment does have a unzip operation, and ther you can see the special handling of directory entries in a zip file.
You are iterating over zip entries in two different ways:
Iteration 1:
for (Enumeration<?> em = zipFile.entries(); em.hasMoreElements();) {
Iteration 2:
ZipEntry outerZipEntry = zipInputStream.getNextEntry();
Just do one or the other. Either use the ZipFile API or the ZipInputStream API. I strongly suspect that is where the NullPointerException is coming from.

Error in Selecting multiple files into one zip and downloading the zip file?

<% // Set the content type based to zip
response.setContentType("Content-type:text/zip");
response.setHeader("Content-Disposition", "attachment; filename=mytest.zip");
// List of files to be downloaded
List files = new ArrayList();
files.add(new File("C:/first.txt"));
files.add(new File("C:/second.txt"));
files.add(new File("C:/third.txt"));
ServletOutputStream out1 = response.getOutputStream();
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(out1));
for (Object file : files)
{
//System.out.println("Adding file " + file.getName());
System.out.println("Adding file " + file.getClass().getName());
//zos.putNextEntry(new ZipEntry(file.getName()));
zos.putNextEntry(new ZipEntry(file.getClass().getName()));
// Get the file
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
} catch (Exception E) {
// If the file does not exists, write an error entry instead of file contents
//zos.write(("ERROR: Could not find file " + file.getName()).getBytes());
zos.write(("ERROR: Could not find file" +file.getClass().getName()).getBytes());
zos.closeEntry();
//System.out.println("Could not find file "+ file.getAbsolutePath());
continue;
}
BufferedInputStream fif = new BufferedInputStream(fis);
// Write the contents of the file
int data = 0;
while ((data = fif.read()) != -1) {
zos.write(data);
}
fif.close();
zos.closeEntry();
//System.out.println("Finished adding file " + file.getName());
System.out.println("Finished adding file " + file.getClass().getName());
}
zos.close();
%>
this is my actualy program , want to zip multiple file and then downloading it , is wat i am doing the way is right or wrong , am new to JAVA programming , can you help me out ???
Your for loop should look like this:
for (File file : files) {
...
or
for (String file : files) {
...
The way you declared file variable, makes compiler assume it's an Object, and not a File instance. Thus, you get compilation error, because there is no FileInputStream constructor accepting an Object. The file must either be a File or a String containing absolute path to a file.
Another error is the way, you're passing file's name to the ZipEntry.
Using:
file.getClass().getName()
will result in "java.io.File" or "java.lang.String", and not the file name.
To set the proper name of the file, use File#getName().

Categories