You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Ender Shorty <en...@gmail.com> on 2006/11/10 05:11:19 UTC

Outputing a file to user (correctly getting ahold of the getOutputStream method)

Hello all,

I've searched around the forums attempting to discover a way to output a
file to the user.  What I'm trying to do is after creating a pdf file with
JasperReports i'd like to output it to the user.  I use Tapestry 4.02.  It
looks like the old way was to do something like this...

Make a method like the following a a listener, such as from a DirectLink or
whatever.

(The Document is just a class that holds the file information you want to
send to the user.)

public void downloadAction(IRequestCycle cycle)
{
    try
    {
        HttpServletResponse response =
        cycle.getRequestContext().getResponse();


        byte[] data = new byte[1024];
        FileInputStream in = document.getFileInputstream();


        response.setHeader("Content-disposition",
          "inline; filename=" +
           document.getFileName());
        response.setContentType(document.getMimeType());
        response.setContentLength(new Long(document.getSize()).intValue());
        ServletOutputStream out = response.getOutputStream();

        int bytesRead = 0;
        while ((bytesRead = in.read(data)) > -1)
        {
            out.write(data, 0 , bytesRead);
        }
        in.close();
        response.flushBuffer();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
}

Now it output's a pdf file correctly, and everything seems to work
fine, but looking at the log, i get serveral of these:
javax.servlet.ServletException: getOutputStream() has already been
called for this response

Apparently the new correct way is to create a service.  Does anyone
have an example of outputing a file with a service?
Thank you very much for any assistance.

Re: Outputing a file to user (correctly getting ahold of the getOutputStream method)

Posted by Jiří Mareš <Ji...@svt.cz>.
Hi,

it is not much difficult: First the URL to servise is http://your.server/your.app.context/app?service=pdf_report&pdf=xx

where the pdf_report is the name of the service and attribute pdf specified what report to return (you can use any
attributes you want and need).

Then you create the service:

public class PdfReportServise implements IEngineService {
   protected HttpServletResponse response;
   protected LinkFactory linkFactory;

   public void setResponse(HttpServletResponse response) {
      this.response = response;
   }

   public void setLinkFactory(LinkFactory linkFactory) {
      this.linkFactory = linkFactory;
   }

   public String getName() {
      return "pdf_service";
   }

   public void service(IRequestCycle cycle) throws IOException {
      ... first parse you parameters ...
      ... generate the report or open the file with report ...
      response.setHeader(...); eg. Content-Disposition ...
      response.setContentType("application/pdf");
      try {
         OutputStream os = response.getOutputStream();
         ... write your data ...
      } catch (IOException e) {
         throw new ApplicationRuntimeException(e);
      }
   }

   public ILink getLink(boolean post, Object parameter) {
      Map params = new HasMap();
      params.put("param1", (String) ((Object[]) parameter)[0]);
      ... put all parameters ...
      return linkFactory.constructLink(this, post, params, false); //the last false means not to add jsessionid, true
means add if appropriate
   }

}

Then you can use in template:

<a href="" jwcid="pdfReport">Get the report</a>

and in page specification:

<component id="pdfReport" type="serviceLink">
   <binding name="service" value="literal:pdf_report"/>
   <binding name="parameters" value="{'...'}"/>  <!-- create the parameters for service -->
</component>

I hope i didn't miss anythink ...


Jirka
To add the service into application add to your hivemind.xml (If you have none create it in META-INF directory):

<module id="your.package" version="1.0.0">
   <service-point id="PdfReport" interface="org.apache.tapestry.engine.IEngineService">
      <invoke-factory>
        <construct class="instance:your.package.PdfReportService"/>
      </invoke-factory>
   </service-point>
   <contribution configuration-id="tapestry.services.ApplicationServices">
      <service name="pdf_report" object="service:your.package.PdfReportService"/>
   </configuration>
</module>

Ender Shorty napsal(a):
> Hello all,
> 
> I've searched around the forums attempting to discover a way to output a
> file to the user.  What I'm trying to do is after creating a pdf file with
> JasperReports i'd like to output it to the user.  I use Tapestry 4.02.  It
> looks like the old way was to do something like this...
> 
> Make a method like the following a a listener, such as from a DirectLink or
> whatever.
> 
> (The Document is just a class that holds the file information you want to
> send to the user.)
> 
> public void downloadAction(IRequestCycle cycle)
> {
>    try
>    {
>        HttpServletResponse response =
>        cycle.getRequestContext().getResponse();
> 
> 
>        byte[] data = new byte[1024];
>        FileInputStream in = document.getFileInputstream();
> 
> 
>        response.setHeader("Content-disposition",
>          "inline; filename=" +
>           document.getFileName());
>        response.setContentType(document.getMimeType());
>        response.setContentLength(new Long(document.getSize()).intValue());
>        ServletOutputStream out = response.getOutputStream();
> 
>        int bytesRead = 0;
>        while ((bytesRead = in.read(data)) > -1)
>        {
>            out.write(data, 0 , bytesRead);
>        }
>        in.close();
>        response.flushBuffer();
>    }
>    catch (IOException e)
>    {
>        e.printStackTrace();
>    }
> }
> 
> Now it output's a pdf file correctly, and everything seems to work
> fine, but looking at the log, i get serveral of these:
> javax.servlet.ServletException: getOutputStream() has already been
> called for this response
> 
> Apparently the new correct way is to create a service.  Does anyone
> have an example of outputing a file with a service?
> Thank you very much for any assistance.
> 

-- 
Jiří Mareš (mailto:Jiri.Mares@svt.cz)
ČSAD SVT Praha, s.r.o. (http://www.svt.cz)
Czech Republic

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org