Hi Chris,

I use a very similar approach with good success. But I created a class that implements StreamResponse since I am generating the PDF on the fly. I also have a version designed for existing files that returns a FileInputStream in getStream().

In prepareResponse(), you can add the "Content-Disposition" header to specify whether the file is displayed or downloaded:

            response.setHeader("Content-Disposition", "inline; filename=" + filename );
or
           response.setHeader("Content-Disposition", "attachment; filename=" + filename);

I also find it helpful to specify an expiration and content length (if available):

        response.setHeader("Expires", new DateTime().withZone(DateTimeZone.UTC).toString(RFC1123_DATE_FORMAT));

        response.setContentLength((int) new File(getFilespec()).length());

Charles

-----

Full class:

public class PdfStreamResponse
implements StreamResponse
{
    public static final String RFC1123_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss 'GMT'";

    private InputStream is;

    private String filename = "default";

    public PdfStreamResponse(InputStream is, String... args)
        {
        this.is = is;
        if (args != null)
            {
            this.filename = args[0];
            }
        }

    public String getContentType()
        {
        return "application/pdf";
        }

    public InputStream getStream() throws IOException
        {
        return is;
        }

    public void prepareResponse(Response response)
        {
        response.setHeader("Content-Disposition", "inline; filename=" + filename + ".pdf");

        // Set special headers to work around a bug in IE with https.
        response.setHeader("Cache-Control", "max-age=0");
        response.setHeader("Pragma", "public");

        // Set to expire immediately so browser won't cache!
        response.setHeader("Expires", new DateTime().withZone(DateTimeZone.UTC).toString(RFC1123_DATE_FORMAT));
        }

}

On 11/15/21 8:27 AM, Christopher Dodunski (Tapestry) wrote:
Hi all,

Inserting a simple <a href="brochure.pdf" download="true"> type link in a Tapestry template so visitors can download a PDF is straightforward enough.

I'd like to shift this to inside the controller, however, so that some code for analytical purposes can be added.

A quick Google search revealed the code example below, from around seven years ago.  Just wondering whether this is still the right approach.  Also, it's not clear how browsers might treat this 'stream response' - download or display?

Happy to see any better approaches.

Regards,

Chris.


public Object onBrochure(){
    final File getFile();
    final OutputStreamResponse response = new OutputStreamResponse() {

        public String getContentType() {
            return "application/pdf";
        }

        public void prepareResponse(Response response) {
            response.setHeader ("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
        }

        @Override
        public void writeToStream(OutputStream out) throws IOException {
            try {
                InputStream in = new FileInputStream(file);
                IOUtils.copy(in,out);
                in.close();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    };
    return response;
}

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


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

Reply via email to