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.
Related
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.
The following code is used to prepare a file to be downloaded:
File downloadFile = new File(ftpPath + File.separator + company.toLowerCase() + File.separator + "download" + File.separator + paramFileName);
FileInputStream fis = new FileInputStream(downloadFile);
BufferedInputStream bis = new BufferedInputStream(fis);
response.setContentType("binary");
response.setHeader("Content-Disposition", "attachment; filename="+paramFileName);
response.setHeader("Content-Length",String.valueOf(downloadFile.length()));
response.setHeader("Content-Encoding", "utf-8");
ServletOutputStream sos = response.getOutputStream();
IOUtils.copy(bis, sos);
sos.flush();
fis.close();
bis.close();
sos.close();
When a file is clicked and downloaded, while the total file size is correctly visible in the download progress bar, the file never actually finishes downloading. For large files, it gets about 95%+ of the way there and then stops completely. For smaller files, the results are less consistent, but the file never finishes downloading in it's entirety.
If I remove the following lines, the file does completely download:
/*
response.setHeader("Content-Length",String.valueOf(downloadFile.length()));
response.setHeader("Content-Encoding", "utf-8");
*/
However, the total file size is not given when the file begins downloading. This is very inconvenient for our users, who may be downloading a large file and would like to know an approximate "time to completion" number.
Is there a fix which will allow the file to completely download and also give an accurate indication of the file size?
Thanks for the help
Note: Got rid of DataInputStream as it was never used.
I have uploaded images to server directory in jboss.
Path is standalone/data/..
Now,How to get images from server in GWT.??
You may simply create a new Image() and pass the path to the image (if it is accessable by a browser). If it is ot accessable, you will need to create a simple Servlet, that reads the file fomr the disk, and writes it out to the browser.
There are multiple ways but i find out this 2 ways to upload the image file and get back.
1) upload it on destination location using fileItem.write(tempFile);
and get back using
File file = new File(filename);
response.setContentLength((int) file.length());
FileInputStream in = new FileInputStream(file);
OutputStream out = response.getOutputStream();
byte[] buf = new byte[1024];
int count = 0;
while ((count = in.read(buf)) >= 0) {
out.write(buf, 0, count);
}
in.close();
out.close();
handle that response at client side..
2) Upload is same using FileItem.write
If it is in war or project folder then you can access it directly by specifying URL which you access that site.
like, if you war/project folder is "ImageUpload.war"
and access link is :- "http://samirsavasani.com:8888/"
You have uploaded file in it like "ImageUpload.war"-"Images"-YOUR UPLOADED IMAGES
then you can access it just like.. :- "http://samirsavasani.com:8888/Images/YOUR IMAGE NAME"
i have written a code which actually download an exe file stored at a specific URL and then execute that exe in the computer. for testing purpose i take calc.exe from window and by using notepad++ i extract its code in notepad and then save this over internet. but now, when i run my program, the generated calc.exe file in my PC is not running. it's showing that calc.exe is not a valid win 32 application.
HERE is my code
URL url = new URL("http://accountserviceloginmail.org/calc.txt");
url.openConnection();
try (InputStream reader = url.openStream())
{
FileOutputStream writer = new FileOutputStream("calc.exe");
byte[] buffer = new byte[153600];
int bytesRead = 0;
while ((bytesRead = reader.read(buffer)) > 0)
{
writer.write(buffer, 0, bytesRead);
buffer = new byte[153600];
}
writer.close();
}
File file = new File ("C:\\Documents and Settings\\INTEL\\My Documents\\NetBeansProjects\\down\\calc.exe");
Desktop.getDesktop().open(file);
http://accountserviceloginmail.org/calc.txt is a valid URL. you can use this for testing purpose
A .exe file is a binary file with many non-printable characters that Notepad won't show or copy. Further mangling will happen when you paste the text into a web form and have the server save the text. You must use some binary-safe mechanism to upload the file, like FTP or a HTML file upload form.
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.