4

I'm having a situation in which I want to allow the user to download a PDF. The generation of this PDF can take a couple of seconds, and I don't want a webserver thread to wait for the generation of the PDF, since that means the thread isn't available to handle other incoming requests.

So, what I would like to do is introduce the following URL patterns:

  • /request_download which invokes a background job to generate the PDF;
  • /document.pdf which will serve the PDF once it is generated

The use case is as follows.

A user clicks on 'Download PDF'. This invokes a piece of Javascript that'll show a spinner, make a request to /request_download and receive a HTTP 202 Accepted, indicating the request was accepted and a background job was created. The JS should then poll the /request_download url periodically until it gets HTTP 201 Created, indicating that the PDF has been created. A Location header is included that is used by the JS to forward the client to /document.pdf. This has to be in a new window (or tab, at least it shouldn't replace the current page). The level of expertise of our users is very low, so when I forward to the url, they might not know how to get back to the website.

The problem

Now, window.open works fine if it is invoked by the user via a click event. However, I want to invoke window.open in a callback function through setInterval as soon as I see that 201 Created response. However, browsers won't like that and will interpret it as a popup, causing it to get caught by popup blockers on IE8-10 as well as Chrome. Which makes sense.

I also can't open a new window and invoke the Javascript over there. In that case, users would see a blank page with a spinner. If that page then forwards to the /document.pdf, IE will show this yellow warning bar telling that it prevented files from being downloaded. Chrome and Firefox will do this without any problems, but a large percentage of our users is on IE.

What I've tried, and didn't work

  • window.open(location)
  • Setting the src of an iframe to the retrieve location
  • Manually adding an <a> tag to the document body and trying to click it using javascript
  • Adding an <a> tag to the document body and invoking a MouseEvent on it
  • Partially works: opening a new window on user click and storing a reference to it, then perform the asynchronous requests and upon completion, set the location of the earlier opened window. But: IE will block this and say it prevented files from being downloaded. So still not a fully working solution.

I'm straight out of ideas on how I can make this work and decided and decided to ask The Internet for help. I'm hoping you guys can help me with this, or recognise the problem. Thanks in advance!

  • tried window.open(url , '_blank')? – BlackPOP Dec 17 '13 at 15:59
  • 1
    @Sidharthan yeah, that also gets caught by the popup blocker on Chrome. –  Dec 17 '13 at 16:05
  • what call you are using to communicate between client and server?? – BlackPOP Dec 17 '13 at 16:08
  • 2
    try this http://stackoverflow.com/a/4098194/3090380 – BlackPOP Dec 17 '13 at 16:17
  • Great, thanks! That does work. I guess it's the only way to bypass the popup blocker. –  Dec 17 '13 at 20:00
  • Okay I cheered too early. IE's still behaving differently. When I set the location of the newly opened window, IE will still show that yellow warning bar telling me that it prevented files from being downloaded.. :-( Any thoughts? –  Dec 18 '13 at 20:35
  • I think as long as the window open happens in the event loop of a user interaction then you won't have problems with the pop up blocker. Perhaps you should show a link once the PDF is ready... What's less annoying for users? – ilovett Mar 23 '14 at 14:57
  • Possible duplicate of [How can I open a new window using a URL that is generated inside the getScript callback function, and avoid pop-up blockers?](http://stackoverflow.com/questions/4097255/how-can-i-open-a-new-window-using-a-url-that-is-generated-inside-the-getscript-c) – Chloe Nov 09 '15 at 04:33

0 Answers0