I have just created small jsp file in which I am downloading a jar file from weblogic server that is installed in my computer through eclipse using the following piece of code which I grabbed from net. But when I try the jar file, it says it is corrupt. The sizes of original and downloaded jar files are identical. I can download and open text files using the code. What is wrong in the code?
<%
String filename = "Words2.jar";
String filepath = "C:\\Users\\OD00259\\Desktop\\";
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition","attachment; filename=\"" +
filename + "\"");
java.io.FileInputStream fileInputStream=new java.io.FileInputStream
(filepath + filename);
int i;
while ((i=fileInputStream.read()) != -1) {
out.write(i);
}
fileInputStream.close();
%>
Try Change the content-type to application/java-archive. Also set the content-length header to include the size of the file.
Also, I would recommend you to use some checksum tools like md5sum for verifying the file downloads comparison instead of relying on the size to compare.
Related
I am running a standalone java process which writes data to multiple xlsx files in a parent target directory and upon completion, the entire target directory is zipped and uploaded to cloud and a download link is provided to the user. The xlsx file names and the name of the zip file is user defined and not possible to change.
The issue is with the names of the xlsx files created. If the filename selected by the user is Japanese, like
サイン色紙プレゼントCPN_第2.xlsx
the corresponding file that is created in the system is of the form:
??????????CPN_?2?.xlsx
The same files are being uploaded to cloud and user is seeing garbled file names. However, the Japanese name of the zip file is not garbled and is in Japanese only.
Following is the code sample for creating xlsx files:
String fileName = userGivenName + "_" + randomUUID + ".xlsx";
File file = new File(tmpParentDirectoryName, fileName);
FileOutputStream outputStream = new FileOutputStream(file);
workbook.write(outputStream);
In this case the absolute path of the xlsx file created is like :
/tmpDirectoryPath/??????????CPN_?2?_0c6b37ee-97c4-44d4-b80d-dfe5eafe0045.xlsx
Just like above there are multiple xlsx files created in the same tmpDirectory
Upon completion following is the code sample to create zip files and upload to cloud:
File[] files = getFilesInFolder(tmpDirectory);
if (ArrayUtils.isEmpty(files)) {
continue;
}
File zipFile = new File(targetDirectory, compressedFileName);
createZipFile(files, zipFile);
String url = uploadFile(compressedFileName, zipFile);
Following piece of code writes data to zip file:
public static void createZipFile(File[] files, File zipFile) {
if (ArrayUtils.isEmpty(files)) {
return;
}
byte[] buffer = new byte[1024];
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile));
try {
for (File file : files) {
FileInputStream fis = new FileInputStream(file);
try {
String fileName = URLDecoder.decode(file.getName(), "UTF-8");
ZipEntry zipEntry = new ZipEntry(fileName);
zos.putNextEntry(zipEntry);
int length;
while ((length = fis.read(buffer)) > 0) {
zos.write(buffer, 0, length);
}
zos.closeEntry();
} finally {
IOUtils.closeQuietly(fis);
}
}
} finally {
IOUtils.closeQuietly(zos);
}
}
The uploaded zip file has the correct Japanese name but the zip entries of the zip file have garbled xlsx filenames.
The standalone java process has following encoding options:
-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8
Following is the output of the locale command:
locale
LANG=en_IN.UTF-8
LC_CTYPE="en_IN.UTF-8"
LC_NUMERIC="en_IN.UTF-8"
LC_TIME="en_IN.UTF-8"
LC_COLLATE="en_IN.UTF-8"
LC_MONETARY="en_IN.UTF-8"
LC_MESSAGES="en_IN.UTF-8"
LC_PAPER="en_IN.UTF-8"
LC_NAME="en_IN.UTF-8"
LC_ADDRESS="en_IN.UTF-8"
LC_TELEPHONE="en_IN.UTF-8"
LC_MEASUREMENT="en_IN.UTF-8"
LC_IDENTIFICATION="en_IN.UTF-8"
LC_ALL=
Can someone direct me as to what am I doing wrong here ? I want the same filenames to be uploaded as given by the user.
I was finally able to crack this.
The issue was with the system properties of the mesos slave that was executing the java process.
The process on the slave was started by a mesos master scheduler using a startup script. Due to this the default java locale properties were not being set up properly on the slave.
I added the following line to the start-up script of the slave:
export LANG=en_IN.UTF-8
Upon explicitly adding the locale property to the start-up script, was able to resolve the issue.
I am using MultipartFile to upload file by using multipartFile.transferTo(new java.io.File(saveDirectory,fileName));. How MultipartFile getting file path. In file upload we will get only file name.
My code is:
if (null != files && files.size() > 0) {
for (MultipartFile multipartFile : files) {
fileName = multipartFile.getOriginalFilename();
multipartFile.transferTo(new java.io.File(saveDirectory, fileName));
System.out.println("kkkkkkkkk" + fileName);
nameoffile = fileName;
fileNames.add(fileName);
//Handle file content - multipartFile.getInputStream()
}
}
import com.oreilly.servlet.MultipartRequest;
You can use MultipartRequest m=new MultipartRequest(request,"d:/new");
MultipartFile.getOriginalFilename may contain path information from the client filesystem depending on the browser you are using. Most browsers like Firefox and Chrome will include include filename without path information. IE at one time did include the complete path information but not sure if that's still true with newer versions of IE.
For more information, see the MultipartFile reference documentation.
I'm trying to download (and later extract) a zip file from my dropbox account using this code
URL url = new URL("-");
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
try (InputStream stream = con.getInputStream()) {
Files.copy(stream, Paths.get(parent.getAbsolutePath() + File.separator + "zippedCache.zip"));
}
The file I'm trying to download is a folder with another folder in it (empty). When I attempt to open the zipped folder, I get something along the lines of "cannot open the folder the compressed zipped folder is invalid" (translated using Google translator). When I unzip it, it's empty.
Can anyone explain what the problem here is?
Edit: Also, the zip folder is empty when I download it using Java, however downloading it normally through a web browser works fine.
Please verify your code again using a HttpURLConnection. This should work out.
For using Https you would need something like urlConnection.setSSLSocketFactory or similar.
You should try to read the InputStream in parts into a byte array and write into a FileOutputStream. It's simpler I think.
Example:
InputStream stream = con.getInputStream();
byte[] buffer = new byte[4096];
FileOutputStream out = new FileOutputStream("anything.zip");
while (stream.read(buffer) != -1) {
out.write(buffer);
}
I have a Java servlet that implements a file download. It includes the following code:
String filename = request.getParameter("filename");
File file = new File(filename);
FileInputStream inputStream = null;
ServletOutputStream outputStream = response.getOutputStream();
ServletContext servletContext = getServletContext();
String mimeType = servletContext.getMimeType(filename);
if (mimeType == null)
mimeType = "application/octet-stream";
logger.trace("MIME type for " + filename + " is " + mimeType);
response.setContentType(mimeType);
response.setContentLength((int)file.length());
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
inputStream = new FileInputStream(file);
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
if (inputStream != null)
inputStream.close();
On the server we have a file.tar.gz, and when the browser sends the request to download that file, I see a line in the log file saying that the "MIME type for file.tar.gz is application/x-gzip". But when we compare the file that the browser saved to the file on the server, they are not the same.
Then I commented out the "if (mimeType == null)" line so that the MIME type would always be set to "application/octet-stream", and the downloaded file still wasn't identical to the one on the server.
Any idea why the downloaded file isn't exactly the same as the file on the server?
EDIT: This is really strange. I tested a text file, a PDF file, a ZIP file (created in Windows), a JPG file, and they all download exact copies. Just this file.tar.gz doesn't get downloaded exactly for some reason (on the server it's 882,273 bytes, and the downloaded copy is 881,968 bytes).
EDIT 2: When I use curl to download the file.tar.gz, it gets saved as an exact copy, so that tells me there's nothing wrong with the servlet code. Chrome is modifying the file before it saves it for some reason. Could Chrome be detecting that the file is a gzipped file and thinks that the server compressed the response (when it really didn't), so it tries to uncompress it? Then again the file that Chrome saves is smaller than the file on the server...
This problem occurred due to a bug in Chrome, as described here:
https://code.google.com/p/chromium/issues/detail?id=268085
Our web server was configured to use HTTP gzip compression for everything sent back to the browser, so due to the Chrome bug, it ended up saving the file with another layer of gzip compression.
I'm trying to zip files from server into a folder using ZipOutputStream.
After archive download it can't be opened after double click. Error "The compressed (zipped) folder is invalid" occures. But if I open it from context menu - > 7zip -> open file it works normal. What can be reason of the problem?
sourceFileName="./file.txt"'
sourceFile = new File(sourceFileName);
try {
// set the content type and the filename
responce.setContentType("application/zip");
response.addHeader("Content-Disposition", "attachment; filename=" + sourceFileName + ".zip");
responce.setContentLength((int) sourceFile.length());
// get a ZipOutputStream, so we can zip our files together
ZipOutputStream outZip = new ZipOutputStream((responce.getOutputStream());
// Add ZIP entry to output stream.
outZip.putNextEntry(new ZipEntry(sourceFile.getName()));
int length = 0;
byte[] bbuf = new byte[(int) sourceFile.length()];
DataInputStream in = new DataInputStream(new FileInputStream(sourceFile));
while ((in != null) && ((length = in.read(bbuf)) != -1)) {
outZip.write(bbuf, 0, length);
}
outZip.closeEntry();
in.close();
outZip.flush();
outZip.close();
7Zip can open a wide variety of zip formats, and is relatively tolerant of oddities. Windows double-click requires a relatively specific format and is far less tolerant.
You need to look up the zip format and then look at your file (and "good" ones) with a hex editor (such as Hex Editor Neo), to see what may be wrong.
(One possibility is that you're using the wrong compression algorithm. And there are several other variations to consider as well, particularly whether or not you generate a "directory".)
It could be that a close is missing. It could be that the path encoding in the zip cannot be handled by Windows. It might be that Windows has difficulty with the directory structure, or that a path name contains a (back)slash. So it is detective work, trying different files. If you immediately stream the zip to the HTTP response, then finish has to be called i.o. close.
After the code being posted:
The problem is the setContentLength giving the original file size. But when given, it should give the compressed size.
DataInputStream is not needed, and one should here do a readFully.
responce.setContentType("application/zip");
response.addHeader("Content-Disposition", "attachment; filename=file.zip");
//Path sourcePath = sourceFile.toPath();
Path sourcePath = Paths.get(sourceFileName);
ZipOutputStream outZip = new ZipOutputStream((responce.getOutputStream(),
StandardCharsets.UTF-8);
outZip.putNextEntry(new ZipEntry(sourcePath.getFileName().toString()));
Files.copy(sourcePath, outZip);
outZip.closeEntry();
Either finish or closethe zip at the end.
outZip.finish();
//outZip.close();
in.close();
I am not sure (about the best code style) whether to close the response output stream already oneself.
But when not closing finish() must be called, flush() will not suffice, as at the end data is written to the zip.
For file names with for instance Cyrillic letters, it would be best to add a Unicode charset like UTF-8. In fact let UTF-8 be the Esperanto standard world-wide.
A last note: if only one file one could use GZipOutputstream for file.txt.gz or query the browser's capabilities (request parameters) and deliver it compressed as file.txt.