PDA

View Full Version : How to implement a file download



smv
Sep 7th, 2004, 09:55 PM
Hi!

I have a controller which asks the user a few questions which are needed to produce a report output as either a PDF or a ZIP file. I am using a FOP based PDF creation mechanism and depending on the user request, either keeping it as a PDF or ZIPing the report output.

Now, how do I handle displaying this file to the client? Since these files are small, I was thinking of keeping them in a session variable and when requested, to display the output. However, how do I then display this data to the user? Do I just create a JSP file which outputs the bytes to the "out" stream and make sure that the view name as defined in my ???-servlet.xml file uses either a ZIP or PDF extension?

Thanks!
smv

smv
Sep 8th, 2004, 12:37 PM
In case anyone else was wondering how to get a solution to work, I managed to get the following to work:
<%@ page import="java.io.*" %>
<%@ page import="...PDFDocument" %>
<%@page contentType="application/pdf"%><%
PDFDocument pdfDocument = &#40;PDFDocument&#41;request.getSession&#40;&#41;.getAttribute&#40;"pdfDocument"&#41;;
OutputStream outputStream = response.getOutputStream&#40;&#41;;
InputStream inputStream = pdfDocument.getInputStream&#40;&#41;;
byte&#91;&#93; buffer = new byte&#91;32 * 1024&#93;;
int bytesRead = 0;
while &#40;&#40;bytesRead = inputStream.read&#40;buffer&#41;&#41; >= 0&#41; &#123;
outputStream.write&#40;buffer, 0, bytesRead&#41;;
&#125;
outputStream.flush&#40;&#41;;
outputStream.close&#40;&#41;;
inputStream.close&#40;&#41;;
request.getSession&#40;&#41;.removeAttribute&#40;"pdfDocument"&#41;;
return;
%>

fmourioux
Sep 8th, 2004, 02:36 PM
Hi smv,

For me i use a simple way without jsp : the return null method.


public class AfficherFichierController implements Controller&#123;
private static Log log = LogFactory.getLog&#40;AfficherFichierController.class&#41; ;

private AuthentificationManager mgrAuthentification = null;
private CommunicationManager mgrCommunication = null;

public void setAuthentificationManager&#40;AuthentificationManager mgr&#41;&#123;
this.mgrAuthentification=mgr;
&#125;

public void setCommunicationManager&#40;CommunicationManager mgr&#41;&#123;
this.mgrCommunication=mgr;
&#125;

public ModelAndView handleRequest&#40;HttpServletRequest request, HttpServletResponse response&#41; throws Exception &#123;

String id=request.getParameter&#40;"idFichier"&#41;;
Fichier fichier=mgrCommunication.getFichier&#40;id&#41;;

if &#40;fichier.getData&#40;&#41;!=null&#41;&#123;
byte&#91;&#93; b = fichier.getData&#40;&#41;;

response.setBufferSize&#40;&#40;int&#41;fichier.getTaille&#40;&#41;&#41;;
response.setContentType&#40;fichier.getContentType&#40;&#41;&#41;;
response.setContentLength&#40;&#40;int&#41;fichier.getTaille&#40;&#41; &#41;;

ServletOutputStream ouputStream = response.getOutputStream&#40;&#41;;
ouputStream.write&#40;b,0,&#40;int&#41;fichier.getTaille&#40;&#41;&#41;;
ouputStream.flush&#40;&#41;;ouputStream.close&#40;&#41;;

&#125;

return null;
//return new ModelAndView&#40;"afficherFichierView","fichier",fichier&#41;;
&#125;
&#125;

Hope it will help u !

Fabien.

smv
Sep 8th, 2004, 03:21 PM
Thanks Fabien!

That is such a sweet controller you've implemented! I'd much rather keep my code in the controller rather than in view technology. I never thought about the HttpServletResponse made available to the handRequest method.

Thanks again,
smv

kdcho
Dec 1st, 2004, 04:59 AM
Hi Fabien,

Can you show me how to call you controller into a jsp and how to configure the application-servlet.xml to define it?

Thanks,


Hi smv,

For me i use a simple way without jsp : the return null method.


public class AfficherFichierController implements Controller&#123;
private static Log log = LogFactory.getLog&#40;AfficherFichierController.class&#41; ;

private AuthentificationManager mgrAuthentification = null;
private CommunicationManager mgrCommunication = null;

public void setAuthentificationManager&#40;AuthentificationManager mgr&#41;&#123;
this.mgrAuthentification=mgr;
&#125;

public void setCommunicationManager&#40;CommunicationManager mgr&#41;&#123;
this.mgrCommunication=mgr;
&#125;

public ModelAndView handleRequest&#40;HttpServletRequest request, HttpServletResponse response&#41; throws Exception &#123;

String id=request.getParameter&#40;"idFichier"&#41;;
Fichier fichier=mgrCommunication.getFichier&#40;id&#41;;

if &#40;fichier.getData&#40;&#41;!=null&#41;&#123;
byte&#91;&#93; b = fichier.getData&#40;&#41;;

response.setBufferSize&#40;&#40;int&#41;fichier.getTaille&#40;&#41;&#41;;
response.setContentType&#40;fichier.getContentType&#40;&#41;&#41;;
response.setContentLength&#40;&#40;int&#41;fichier.getTaille&#40;&#41; &#41;;

ServletOutputStream ouputStream = response.getOutputStream&#40;&#41;;
ouputStream.write&#40;b,0,&#40;int&#41;fichier.getTaille&#40;&#41;&#41;;
ouputStream.flush&#40;&#41;;ouputStream.close&#40;&#41;;

&#125;

return null;
//return new ModelAndView&#40;"afficherFichierView","fichier",fichier&#41;;
&#125;
&#125;

Hope it will help u !

Fabien.

stueccles
Dec 2nd, 2004, 06:17 AM
little trick for streaming bytes in Spring Controllers


String filename = .............
byte&#91;&#93; content = ...............

String mimetype = this.getServletContext&#40;&#41;.getMimeType&#40;filename&#41;;
response.setContentType&#40;mimetype&#41;;
response.setContentLength&#40;content.length&#41;;
FileCopyUtils.copy&#40;content , response.getOutputStream&#40;&#41;&#41;;
return null;

araghavan
Dec 8th, 2004, 01:47 PM
I have a related question.
I have a page that is rendered by a multi action controller. When a download link is used on the page, I would like to download a file but also refresh the view on the page that contains the link. I am unable to do it after out.flush is done, I can not return a ModelAndView. Any thing but returning null is causing "response is already committed" error.

Here is some pseudo code:
public ModelAndView viewDownloadAndUnassignUnusedCouponCodes(HttpServl etRequest request, HttpServletResponse response) throws ServletException {
String offerID = request.getParameter("offerID");
// This does the download/writign to the output stream
downloadUnusedCouponCodes(request, response);
offerControlsDao.unassignCouponCodesFromOffer(offe rID);

// It would be nice to refresh the view but it doesn't work.
// get a "response already committed exception".
return null;
}

araghavan
Dec 8th, 2004, 04:11 PM
Here is some further clarification.
By the time I try to return a ModelView, I am already done doing out.flush. Where out = HttpServeletResponse.getOutputStream();

Is this the reason I am getting erros?
Thanks,
Aruna Raghavan

rob_from_ca
Dec 10th, 2004, 10:58 AM
Once you flush the servlet output stream, the headers have to get sent so that it can send your stream content in the body of the HTTP response. The only option left at that point is to end the response, which will happen when you send Content-Length: number of bytes, or explicitly close the connection.

Essentially, per-request you only get one response. After that, you need some way to make the client initiate a new response.

To do what you want, you'll have to rely on client side scripting or some sort of meta-refresh solution.

araghavan
Dec 13th, 2004, 08:43 AM
Thanks, Rob.

nilesh
Dec 29th, 2004, 12:29 AM
EDIT: This was originally a question but I found the answer.. To cause the browser to download the file (rather than display in the browser if possible) and to provide the correct file name to the browser, do this:


response.setHeader&#40;"Content-Disposition","attachment; filename=\"" + fileName +"\""&#41;;

ericrath
Aug 3rd, 2005, 09:15 PM
FWIW, I ran into an issue with IE6 on Win2K (haven't been able to test IE6 on WinXP yet) when downloading a file through a spring controller over https: IE displayed an error message saying:

"Internet Explorer cannot download blah.html?id=blah from domain.com
Internet Explorer was not able to open this internet site. The request site is either unavailable or cannot be found. Please try again later."

The same controller worked fine with Firefox 1.0.6 on Win2K, and with Safari and Firefox 1.0.6 on Mac OS X.

I had earlier setup all my controllers to set the cacheSeconds property to 0 (in an effort to prevent caching any of these pages on the client). When I removed this property from the file download controller, the problem in IE6/Win2K changed - I can now save the file, but choosing to open the file brings up the "save" dialog. Once I thought about it, a download controller wouldn't want to set a no-cache header anyway.

The controller set the content-type header using the return from ServletContent.getMimeType(), set the content-length header according to the file size, and set the Content-disposition header to "application; filename="blah.html"".

emanaton
Sep 29th, 2006, 11:59 AM
Greetings,

Many thanks for this artical - it helped me to get to my solution. In my case, I'm running Apache and serving a dynamically generated PDF file that downloads fine in all popular browsers but IE. My working solution was to add the following lines prior to my other header outputs:

/**
* The following Pragma and Cache-Control lines are necessary
* as the overcome an issue that IE has in some server configurations
* when the no-cach header is sent. The two lines override these
* headers, allowing IE to proceed. When not turned on, the error IE
* provides is:
* Internet Explorer cannot download <item URL here instead of item file name> from <domain>.
*
* Internet Explorer was not able to open this Internet site. The requested site is either
* unavailable or cannot be found. Please try again later.
*/
header("Pragma: public");
header("Cache-Control: max-age=0");

Sean P. O. MacCath-Moran
www.emanaton.com

nrk150
May 3rd, 2007, 04:08 AM
Hi here is my controller in Spring framework.

public ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {

String subsId = request.getParameter("subscriberId");
String logFileName = null;
String logFilePath = null;
boolean checkFile = false;
boolean checkFileFlag = false;
String checkFileString = null;
String appServerName = null;
appServerName = reloadableCachingAttributes
.getPropertyValue("vp.apps.cache.serveridentifier");
request.setAttribute("appServerName", appServerName);
Map<String, String> logFile = null;

if (subsId != null) {
StringBuffer sbLog = new StringBuffer(subsId).append(".log");
String subsLogFileId = sbLog.toString();
subsLogFileId = "Subscriber-" + subsLogFileId;
String logFileDir = reloadableCachingAttributes
.getPropertyValue("vp.apps.cache.logfile.dir");
File f = new File(logFileDir);
File[] strFiles = null;
if (f.isDirectory()) {
strFiles = f.listFiles();
for (int i = 0; i < strFiles.length; i++) {
checkFile = strFiles[i].isFile();
if (checkFile) {
if (subsLogFileId.equals(strFiles[i].getName())) {
logFileName = strFiles[i].getName();
checkFileFlag = true;
logFilePath = logFileDir + "/" + logFileName;

File f1 = new File(logFilePath);
// set the content type
response.setContentType("text/plain");
// set the header and also the Name by which user
// will be prompted to save
response
.setHeader("Content-Disposition",
"attachment; filename=\"Subscriber-100.log\"");

// OPen an input stream to the file and post the
// file contents thru the
// servlet output stream to the client m/c

InputStream in = new FileInputStream(f1);
byte[] bytearray = new byte[(int) f1.length()];
ServletOutputStream outs = response
.getOutputStream();
//final int i1 = 256;
//int bit = i1;
// int i2 = 0;
/*try {
while (bit >= 0) {
bit = in.read();
outs.write(bit);
}
} catch (IOException ioe) {
ioe.printStackTrace(System.out);
}*/
in.read(bytearray);
outs.write(bytearray);
outs.flush();
outs.close();
in.close();
}
}
}
checkFileString = String.valueOf(checkFileFlag);
logFile = new HashMap<String, String>();

logFile.put("checkFileString", checkFileString);
logFile.put("logFilePath", logFilePath);
logFile.put("logFileName", logFileName);
}
} else {
logFileName = "Subscriber Id should not empty ";
}

return new ModelAndView("jobaudits", "subsIdModel", logFile);
}



The problem is
i had a submit button and text box in jsp page and i enter the file name i didnt go to the link. i will automatically downloaded also it shows the contents of the jsp name jobaudits.jsp.

my requirements i had a link. i need to dispaly the file name in the link and when i click the link, the file should be downloaded.
anyone please help me.
Ramkumar

nicoSiegl
May 31st, 2007, 11:37 AM
I have an application using Spring and Freemarker, and I need to have a link on one of the pages that triggers the download of a local pdf file.

I'm sure it's easy, but the solution is currently eluding me.:)
Help?

Nico

nicoSiegl
May 31st, 2007, 12:36 PM
Found a working solution here (http://forum.springframework.org/showthread.php?t=14128).

sensayan
Aug 22nd, 2007, 06:59 AM
Hi
I am facing the same problem..
the text file is not opening. It is opening perfectly in Mozilla but in IE it is stated that file is not found.

If any one has solution already please let me know..

waiting for a fast reply

kpkkpk
Jun 6th, 2008, 11:35 PM
Hi
I am facing the same problem..
the text file is not opening. It is opening perfectly in Mozilla but in IE it is stated that file is not found.

If any one has solution already please let me know..

waiting for a fast reply

I am not sure if this was related to IE7 but here is the solution

response.setHeader("Pragma", "private");
response.setHeader("Cache-Control", "private, must-revalidate");

More details and credit
expisoft dot blogspot dot com/2007/03/ie7-does-not-excel.html

Convert above line to url , am not allowed to post urls