0

I am polling a server, using setInterval, until the pdf's that I want to download are ready...Once the pdfs are ready to download, I clear the interval, and then I call a function

async function DownloadAndOpenPdf(fileId){
    const ret = await Utilities.PostFunction(DownloadReportFileURL, fileId);
    const blob = new Blob([Base64ToBinary.decodeArrayBuffer(ret.Base64EncryptedData)], { "type": ret.MimeType });
    const link = document.createElement('a');
    link.href = window.URL.createObjectURL(blob);
    link.download = ret.FileName + ret.FileExtension;
    link.click();
    window.open(link.href, "_blank");
}

This downloads the pdf, but then I get a message saying that the popup was blocked, however, if I run this function in DevTools the pdf gets downloaded and opens up in a new tab without any issue. If I call that function on a button click event then it works without any issue. What am I missing? how do I fix this to download and open the file without the message saying that the popup was blocked after an interval has been cleared

10
  • 3
    sounds like the browser doesn't think the popup is tied to a user-event. You may have to create a button for the user to click (once the data is ready for download) in order to open the new window. You can also avoid creating a new copy there (i.e. createObjectURL) by opening a window with a URL to an endpoint that returns a file. Commented Jun 9 at 18:47
  • 4
    That's the way popup blockers work. The new window has to be created in a function called from a user action. DevTools is exempted from this restriction. Commented Jun 9 at 19:05
  • 1
    it sounds like your polling function gets the pdf url once its ready. in that case you should show a loader while it's polling, and then once its ready replace the loader with a link for the user to click themselves Commented Jun 9 at 23:03
  • 1
    @Chris that may be what's wanted, but it's not what browser security rules permit. Otherwise, malicious sites could happily and endlessly auto-download all sorts of horrors to your machine without needing any user interaction, or show a bazillion pop-up ads (as used to be the case in older browsers many years ago - it was a plague). Commented Jun 10 at 13:59
  • 1
    Or open the popup with just a "please wait" notice / some sort of loading indicator first, and then replace the URL of the popup afterwards, when the PDF URL has been created. const displayWindow = window.open("placeholder-page.htm", "_blank"); right away when DownloadAndOpenPdf gets invoked via click, and then displayWindow.location.href = link.href later. Commented Jun 12 at 11:38

1 Answer 1

1

Your popup is being blocked because window.open() is being called after the polling interval finishes, not directly in response to a user action.

Browsers allow popups only when they’re triggered synchronously from user gestures (e.g., click events). In your code, the setInterval callback runs asynchronously later, so the open action is no longer tied to the click that started the process — the browser flags it as an unsolicited popup.

Fix:

  • Open a blank tab/window immediately when the user clicks to start polling.
  • During polling, once the PDF is ready, just change the location.href of that already-open window to the Blob URL.
  • This way, the “popup” is approved at the moment of the click, and the browser won’t block it when you update it later. and here is the code.
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Polling + Open PDF</title>
  <script>
    // Simulate API response
    const Utilities = {
      async PostFunction(url, fileId) {
        await new Promise(resolve => setTimeout(resolve, 1000));

        // Valid full base64 of a simple PDF
        const base64 = "JVBERi0xLjQKMSAwIG9iago8PAovQ3JlYXRvciAoUERGIEdlbmVyYXRvcikgCi9UeXBlIC9DYXRhbG9nCi9QYWdlcyAyIDAgUgo+PgplbmRvYmoKMiAwIG9iago8PAovVHlwZSAvUGFnZXMKL0tpZHMgWzMgMCBSXQovQ291bnQgMQo+PgplbmRvYmoKMyAwIG9iago8PAovVHlwZSAvUGFnZQovUGFyZW50IDIgMCBSCi9NZWRpYUJveCBbMCAwIDYxMiA3OTJdCi9Db250ZW50cyA0IDAgUgo+PgplbmRvYmoKNCAwIG9iago8PAovTGVuZ3RoIDM3Cj4+CnN0cmVhbQpCBiAwIDAgMCAwIDAgblQKSGVsbG8gV29ybGQhIFQKRVQKZW5kc3RyZWFtCmVuZG9iago1IDAgb2JqCjw8Ci9UeXBlIC9YUmVmCi9XSUQgWzIgMCAgUl0KPj4KZW5kb2JqCnhyZWYKMCA2CjAwMDAwMDAwMDAgNjU1MzUgZiAKMDAwMDAwMDAxMCAwMDAwMCBuIAowMDAwMDAwMDE4IDAwMDAwIG4gCjAwMDAwMDAwNjUgMDAwMDAgbiAKMDAwMDAwMDAxNzUgMDAwMDAgbiAKMDAwMDAwMDAyNzYgMDAwMDAgbiAKdHJhaWxlcgo8PAovUm9vdCAxIDAgUgo+PgpzdGFydHhyZWYKMzkwCiUlRU9G";

        return {
          Base64EncryptedData: base64,
          MimeType: "application/pdf",
          FileName: "HelloWorld",
          FileExtension: ".pdf"
        };
      }
    };

    const Base64ToBinary = {
      decodeArrayBuffer(base64) {
        const binary = atob(base64);
        const len = binary.length;
        const bytes = new Uint8Array(len);
        for (let i = 0; i < len; i++) {
          bytes[i] = binary.charCodeAt(i);
        }
        return bytes;
      }
    };

    const DownloadReportFileURL = "https://example.com/download";

    function startPollingForPdf(fileId) {
      const popup = window.open('', '_blank');
      if (!popup) {
        alert("Popup blocked. Please allow popups.");
        return;
      }

      popup.document.write("<h2>Generating your report...</h2>");

      let tries = 0;
      const interval = setInterval(async () => {
        tries++;
        if (tries === 5) {
          clearInterval(interval);

          const ret = await Utilities.PostFunction(DownloadReportFileURL, fileId);

          const blob = new Blob(
            [Base64ToBinary.decodeArrayBuffer(ret.Base64EncryptedData)],
            { type: ret.MimeType }
          );

          const blobURL = URL.createObjectURL(blob);
          popup.location.href = blobURL;

          // Optional: trigger download
          const link = document.createElement('a');
          link.href = blobURL;
          link.download = ret.FileName + ret.FileExtension;
          document.body.appendChild(link);
          link.click();
          document.body.removeChild(link);
        }
      }, 1000);
    }
  </script>
</head>
<body>
  <h2>Start polling & open PDF</h2>
  <button onclick="startPollingForPdf('abc123')">Start Polling</button>
</body>
</html>


Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.