• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Ron McLeod
  • paul wheaton
  • Jeanne Boyarsky
Sheriffs:
  • Paul Clapham
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
  • Himai Minh
Bartenders:

File download with servlets

 
Greenhorn
Posts: 3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 60
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 34
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 60
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 265
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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();
 
Don't get me started about those stupid light bulbs.
reply
    Bookmark Topic Watch Topic
  • New Topic