This week's giveaway is in the EJB and other Java EE Technologies forum.
We're giving away four copies of EJB 3 in Action and have Debu Panda, Reza Rahman, Ryan Cuprak, and Michael Remijan on-line!
See this thread for details.
The moose likes Servlets and the fly likes File download with servlets Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of EJB 3 in Action this week in the EJB and other Java EE Technologies forum!
JavaRanch » Java Forums » Java » Servlets
Bookmark "File download with servlets" Watch "File download with servlets" New topic
Author

File download with servlets

Alex Vasconcelos
Greenhorn

Joined: Mar 18, 2002
Posts: 3
Hello all,
Has anyone been able to successfully write servlet code to download files to a client machine that works with both Netscape and IE ?
Currently I have code that generates a file to be downloaded and streams that file back to the client. This works perfectly with Netscape:

response.reset();
response.setContentLength(size);
response.setContentType("application/zip; name=\"" + fileName + "\";");
response.setHeader("Content-Disposition" , "attachment;filename=" + fileName);
response.getOutputStream().write(file);
response.getOutputStream().flush();
response.getOutputStream().close();
With IE I get an error trying to display the page. To make it work with IE all I have to do is remove the line where I set the Content-Disposition header, but this makes IE try to save the file as the name of the servlet. In other words, if the link is http://www.foo.com/aServlet, IE will try to save a file called "aServlet", which is not what I want.
According to RFC's the Content-Disposition hearder is supposed to take care of that, but there seems to be several problems with the way IE handles that.
I am currently using IE 5.5 SP 2. Have also tried this with IE 6.0 and it didn't work.
Any help will be greatly appreciated.
Thanks in advance,
Alex V.
Jim Wang
Ranch Hand

Joined: Oct 04, 2001
Posts: 41
In my case, I don't want browser open the download file, which is in PDF format. I found this piece code from this site and it works. You may try it.
String pdf = req.getParameter("pdfurl");
String filename = pdf.substring(pdf.lastIndexOf("/")+1);

//res.setContentType("application/x-filler");
res.setContentType("application/pdf");
res.setHeader("Content-Disposition","attachment;filename=" + filename );


try{
FileInputStream fileInput = new FileInputStream(pdf);
int numOfBytes = fileInput.available();
byte byteArray[] = new byte[numOfBytes];
int nextByte = fileInput.read(byteArray);
fileInput.close();

OutputStream outStream = res.getOutputStream();
outStream.write(byteArray);
outStream.close();
}
Alex Vasconcelos
Greenhorn

Joined: Mar 18, 2002
Posts: 3
Hi Jim, and thanks for your answer.
Actually I have already tried that and this is what I was talking about when I said IE was giving me problems. Something about the way it handles the Content-Disposition header.
I have gone ahead and coded a work around it which involves putting the generated file in a public directory and redirecting the servlet to that file. This works like a charm ... too bad it didn't work with the Content-Disposition as it should have ... (
Thanks again for your time.
Alex Vasconcelos.
Zakaria Haque
Ranch Hand

Joined: Jan 02, 2002
Posts: 60
IE4 has a bug with handling content disposition header, it has been fixed in IE5. According to MSDN, there is no patches available, on the client end only solution is to upgrade to IE5.
Keeping the file in a public dir and redirecting the client to the file is one solution. If you dont want the user to directly access the file, you can use url mapping. Keep the file in a nonpublic directory, map every request with a specified path to the download servlet, and while linking(href) to the servlet use desired filename. This way, the browser sees a name the link specified although the request go thru the download servlet.


tobe bondhu nouka bherao<br />shonabo gaan aj shara raat
ravi inguva
Ranch Hand

Joined: Feb 07, 2002
Posts: 34
Dear friends
u people try this method if u havent tried this earlier

public void downloadFile(String sourceFilePathName)
throws IOException, ServletException, DownloadException {

if(sourceFilePathName == null)
throw new IllegalArgumentException(String.valueOf((new StringBuffer("File '")).append(sourceFilePathName).append("' not found (1040).")));
//start
File[] root = new File("").listRoots();
boolean local = false;

for(int r=0;r<root.length;r++) {
if(sourceFilePathName.toUpperCase().startsWith((root[r]).toString())) {
local = true;
}
}
File srcDirPath = null;
if(local) {
sourceFilePathName = sourceFilePathName;
}else {
sourceFilePathName = config.getServletContext().getRealPath(sourceFilePathName);
}
//end
//if(config.getServletContext().getRealPath(sourceFilePathName) != null)
// sourceFilePathName = config.getServletContext().getRealPath(sourceFilePathName);

File file = new File(sourceFilePathName);
FileInputStream fileIn = new FileInputStream(file);
long fileLen = file.length();
int readBytes = 0;
int totalRead = 0;
byte b[] = new byte[128];

httpResponse.setContentType("application/x-msdownload");
httpResponse.setContentLength((int)(fileLen));

httpResponse.setHeader("Content-Disposition", "attachment; filename=".concat(String.valueOf(getLocalFileName(sourceFilePathName))));
String xxx="Content-Length: "+fileLen+"\r\n";

try{
while((long)totalRead < fileLen)
{

if(fileLen-totalRead > 128)
{
readBytes = fileIn.read(b, 0, 128);
totalRead += readBytes;
}
else
{ readBytes=fileIn.read(b,0,(int)fileLen-totalRead);
totalRead= totalRead+readBytes; }
httpResponse.getOutputStream().write(b, 0, readBytes);
}
fileIn.close();
//httpResponse.getOutputStream().close();
}catch(java.net.ProtocolException e){
//System.out.println("hai10 "+e);
}
}
Hope This will work for u as i have tried and tested to comeout successfully
n'joy

Originally posted by Alex Vasconcelos:
Hello all,
Has anyone been able to successfully write servlet code to download files to a client machine that works with both Netscape and IE ?
Currently I have code that generates a file to be downloaded and streams that file back to the client. This works perfectly with Netscape:

response.reset();
response.setContentLength(size);
response.setContentType("application/zip; name=\"" + fileName + "\";");
response.setHeader("Content-Disposition" , "attachment;filename=" + fileName);
response.getOutputStream().write(file);
response.getOutputStream().flush();
response.getOutputStream().close();
With IE I get an error trying to display the page. To make it work with IE all I have to do is remove the line where I set the Content-Disposition header, but this makes IE try to save the file as the name of the servlet. In other words, if the link is http://www.foo.com/aServlet, IE will try to save a file called "aServlet", which is not what I want.
According to RFC's the Content-Disposition hearder is supposed to take care of that, but there seems to be several problems with the way IE handles that.
I am currently using IE 5.5 SP 2. Have also tried this with IE 6.0 and it didn't work.
Any help will be greatly appreciated.
Thanks in advance,
Alex V.
Alex Vasconcelos
Greenhorn

Joined: Mar 18, 2002
Posts: 3
Hi again,
Zakaria, that is a good solution. The only thing that made me opt for the other one was the fact that I didn't want to tie the file name to the servlet that will do the downloads. I know that the requirements will demand that we use the same servlet for any number of files and so I would have to either add a new mapping for each file I wanted to download or I would have to add a new servlet. For what we are doing, I think the file in a public directory is not a big problem. I am going to implement a cleanup procedure to delete those files on a regular basis.
As for the code suggested by Ravi, the problem I have is with the Content-Disposition header. I am using IE 5.5 SP2. And it is very frustrating to read about how this bug has been fixed in SP1 and still see it happening.
All I have to do to make it work is to comment out the line where I set the Content-Disposition, and IE recognizes that it is a download, but it doesn't know what the name of the file is, so it uses the servlet name. If I put the header back in, I get the "Can't Display This Page" error ... very strange indeed.
Again, thanks all for taking the time to answer to this posting. I was just hoping there was a consistent answer that we all could use ... \
Alex V.
Zakaria Haque
Ranch Hand

Joined: Jan 02, 2002
Posts: 60
Hi Alex, as long as direct access to the file thru the webserver is ok with your requirements, there is no need to bother with the mapping I mentioned. But it is possible to have one servlet and one url mapping that handles download of any arbitrary number of file.
you can map "domain/path/download/*" to the download servlet. Now if you want to download a file named XXX.xxx you can href to it by
domain/path/download/XXX.xxx?file_identifier=YYY
Here YYY has unique information that the servlet uses to identify the file.
This way you use one mapping and one servlet for any file download.
You can specify the file name thru href.
Graham Thorpe
Ranch Hand

Joined: Mar 25, 2002
Posts: 264
U try this code .I THINK UR PBM IS SOLVED.....
res.setContentType("image/gif");
res.setContentType("application/pdf");
res.setContentType("application/download");
res.setContentType("application/zip");
res.setContentType("application/tar");
res.setContentType("application/doc");
res.setContentType("image/jpg");
res.setContentType("application/word");
res.setContentType("text/plain");
res.setContentType("image/jpeg");
res.setContentType("application/txt");
res.setContentType("application/gif");
res.setContentType("application/jpg");
res.setContentType("text/html");
res.setContentType("text/xml");
res.setContentType("text/vap.wap.wml");
res.setContentType("text,vnd.wap.xml");
res.setContentType("text/vnd.wap.wml");
res.setContentType("multipart/mixed");
res.setContentType("text/html;charset=iso-2022-jp");
res.setContentType("application/vnd.ms-excel");
res.setHeader("Content-Disposition","attachment; filename=\"" + fname + "\";");
}
// end of reference part
java.io.InputStream is = part.getInputStream();
int i;
while ((i = is.read()) != -1)
out.write(i);
out.flush();
out.close();
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: File download with servlets
 
Similar Threads
file download dialog box
repost with more detail on problem of download servlet in Internet Explore
file download dialog box - help me out
need urgent help on file download servlet problem in IE
Content-Disposition: Download file name problem