REST Response as application/pdf

10,537 views
Skip to first unread message

Sebastian Russ

unread,
May 26, 2014, 5:23:54 AM5/26/14
to rest...@googlegroups.com
Hi,

Im trying to create a PDF on the server and provide the generated PDF as a application/pdf response.


    @GET
    @Path(SharedConstants.Paths.METHOD_PATH_DOWNLOAD_REPORT)
    @Produces("application/pdf")
    public Response downloadReport(GwtReportListDTO pResultList) {

        File file = null;
        OutputStream os = null;
        try {
            file = File.createTempFile(new Date().toString(),"pdf");
            os = new BufferedOutputStream(new FileOutputStream(file));
            doPrint(os, pResultList);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            LOGGER.error("Cannot create file",e);
        }
        finally
        {
            IOUtils.closeQuietly(os);
        }

        Response.ResponseBuilder responseBuilder = Response.ok((Object) file);
        responseBuilder.header("Content-Disposition",
                "attachment; filename=test.pdf");
        Response response = responseBuilder.build();
        return response;
    }

How do I have to set the client interface?

@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface RestReportClientInterface extends RestService {

    @GET
    @Path(SharedConstants.Paths.METHOD_PATH_DOWNLOAD_REPORT)
    @Produces("application/pdf")
    public void downloadReport(GwtReportListDTO pResultList,
                               MethodCallback<Response> pCallback);
}

Or should i create the file on the server and show the pdf over the URL?

No answers about RTFdocs ... I dont have the time. Just tell me if its possible or not.

Sorry for the harshness...

best regards

christian

unread,
May 26, 2014, 5:39:38 AM5/26/14
to rest...@googlegroups.com
hi,

not sure if I understand. the server creates the pdf then you probably do not want to have it as blob in your javascript code and rather open a new window (or popup or iframe) with dispose-content header.

it is possible ;)

- christian

Sebastian Russ

unread,
May 26, 2014, 5:46:11 AM5/26/14
to rest...@googlegroups.com, m.kri...@web.de
My intent was to let the browser handle the PDF stuff.

I thought if I send the browser a application/pdf response it will open the "PDF Plugin stuff" and displays the PDF.

I suppose you advice me to create the pdf on the server and show it in a new window?!

thanks for the fast answer!

christian

unread,
May 26, 2014, 5:50:05 AM5/26/14
to rest...@googlegroups.com, kristian
well, you can open it in the same window, i.e. replace you app with the PDF. whether the server creates a tempfile or on the fly is not important for the browser.


On Mon, May 26, 2014 at 10:46 AM, Sebastian Russ <russ.se...@googlemail.com> wrote:
My intent was to let the browser handle the PDF stuff.

I thought if I send the browser a application/pdf response it will open the "PDF Plugin stuff" and displays the PDF.

I suppose you advice me to create the pdf on the server and show it in a new window?!

thanks for the fast answer!

welcome

-christian

Sebastian Russ

unread,
May 26, 2014, 5:59:55 AM5/26/14
to rest...@googlegroups.com, kristian
:) I know.

But my problem is, I dont know how to do it on the fly (with RestEasy and RestyGWT). It doesnt work with the code snippets above. It says on the client it doesnt know the class Response.

My next try would have been to create the PDF on the server, provide the URI and show the PDF using that URI.

christian

unread,
May 26, 2014, 6:10:43 AM5/26/14
to rest...@googlegroups.com, kristian
I see, you want to provide some json data and produce the pdf. the RestService might not be the right tool for this - might be small patch to get this working as well. let me double check the code now . . .

create a temp file on the server is definitely working.

Sebastian Russ

unread,
May 26, 2014, 6:19:30 AM5/26/14
to rest...@googlegroups.com, kristian
cool thx. I think you managed to get what I want to do... ( despite my poor explanation) :D

I already tried to return a Byte[]. Didnt work either.

Sebastian Russ

unread,
May 26, 2014, 6:44:13 AM5/26/14
to rest...@googlegroups.com
Meanwhile I tried the "temp file" approach.

I get following Error if I try to Window.open(pUri , "Test", "");
with pUri = "file:///C:/Entwicklung/tomcat-7.0.52/temp/report6977215234697668293.pdf"

------------Exception-----------
com.google.gwt.core.client.JavaScriptException: (Error) @com.google.gwt.core.client.impl.Impl::apply(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)([JavaScript object(2287), JavaScript object(2286), JavaScript object(2426)]): Access to 'file:///C:/Entwicklung/tomcat-7.0.52/temp/report6977215234697668293.pdf' from script denied     at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:249)
------------------------------------

Is it a tomcat config? Because if i try to paste it in the browser it shows me the pdf... :D


christian

unread,
May 26, 2014, 7:15:46 AM5/26/14
to rest...@googlegroups.com
nope a file url will not do. you need your server to provide that temp pdf via a normal url - just a simple servlet which delivers those temp pdf will do.

the browser will work but from javascript SOP (same origin policy) will apply and once your browser is not on the same machine as the server those file uris will fail as well.


--
You received this message because you are subscribed to the Google Groups "RestyGWT" group.
To unsubscribe from this group and stop receiving emails from it, send an email to restygwt+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Sebastian Russ

unread,
May 26, 2014, 9:53:11 AM5/26/14
to rest...@googlegroups.com
Do you have a solution for the just in time approach?

Would be cool! :D

Décio Sousa

unread,
May 26, 2014, 9:56:26 AM5/26/14
to rest...@googlegroups.com
I ran into the same issue a while ago. I needed to make a REST request which response would be a file to download (PDF, XLS, etc). 
The way I got it to work was actually with two requests (one REST and another plain http via gwt FormPanel) but I'm not sure if there is a better solution with just one request.

The way I did it was the first request is answered with a file token which is then used to set a hidden field on a FormPanel which I then submit to a download servlet on the server. That servlet then responds with the correct content-type which is then handled by the browser.

If you want any implementation details I'm glad to share.

christian

unread,
May 26, 2014, 10:16:16 AM5/26/14
to rest...@googlegroups.com
I would not now of anything else either - the pdf has to come either with a "normal" GET URL or post via the FormPanel.

instead of json payload you might consider sending html query parameters via the FormPanel. or do as Decio suggested.

Sebastian Russ

unread,
May 27, 2014, 2:31:39 AM5/27/14
to rest...@googlegroups.com, m.kri...@web.de
Thank you guys - Especially christian for your help!

The way Decio did it sounds pretty cool, but it is overkill for me.

I split it into 2 requests too now. One Rest to get a "real" url on my Tomcat /temp and one DownloadServlet which serves the File as Application/pdf.

I tried to generate the file in my .war but ServletContext.getResource("/") always returned null...

I know its very "simple". So my last question is, are there any security issues if I do it like this?

christian

unread,
May 27, 2014, 10:17:04 AM5/27/14
to rest...@googlegroups.com, kristian
security issue: make the download servlet accept a simple name, i.e. /downloads/my-super-secret.pdf and store the file locally /temp/my-super-secret.pdf and make sure you deal with only filenames and not path parts in them.

you are welcome . . .  christian

Sebastian Russ

unread,
May 30, 2014, 2:59:17 AM5/30/14
to rest...@googlegroups.com, m.kri...@web.de
Sorry but i have another problem...

No matter what I use to show the PDF, I always get "generated" as the Tab/Window Title... which is the name of HttpServlet path...

Window.open(url, "New Title", "");
Window.Location.assign(url)
Window....

Am I doing something wrong?

christian

unread,
May 30, 2014, 4:50:02 AM5/30/14
to rest...@googlegroups.com, kristian

Sebastian Russ

unread,
Jun 2, 2014, 4:18:58 AM6/2/14
to rest...@googlegroups.com, m.kri...@web.de
Already tried that one ... didnt work... :(

Décio Sousa

unread,
Jun 3, 2014, 1:25:44 PM6/3/14
to rest...@googlegroups.com, m.kri...@web.de
If you simply want to download the file in the same page without opening tabs or windows you can try to use a form panel to submit the request. 
In your index.html add an empty div to handle the content:

<div id="content"></div>

Then just create a form panel to submit to the download servlet:


            formPanel = new FormPanel();
            RootPanel.get("content").add(formPanel);

        formPanel.setSize("0px", "0px");
        formPanel.setVisible(false);
        formPanel.setAction(servletUrl);
        formPanel.setEncoding(FormPanel.ENCODING_URLENCODED);
        formPanel.setMethod(FormPanel.METHOD_POST);

//Set parameters if needed on hidden field - I use this to set the file name retrieved on a previous request
        VerticalPanel verticalPanel = new VerticalPanel();
        if (parameters != null) {
            for (String key : parameters.keySet()) {
                verticalPanel.add(new Hidden(key, parameters.get(key)));
            }
        }

        formPanel.add(verticalPanel);
        formPanel.submit();

On the server side you can try to set these headers so the browser gets the proper filename and content-type:

//Set response headers
        response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
        response.setContentTypeIfNotSet("application/pdf");


Like this it should work in all browsers as a regular file download.


Reply all
Reply to author
Forward
0 new messages