createObjectURL overload resolution failed

I am trying to load a PDF as a blob in JavaScript from the backend, but receive Failed to execute 'createObjectURL' on 'URL': Overload resolution failed. I'm not really sure where to go from here. I've looked at some of the other posts but none seem to deal with PDF, only audio.

The docs for createObjectURL say: "The new object URL represents the specified File object or Blob object", so I'm not sure what I'm doing wrong. (https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL)

From my backend, I set: Content-type: application/octet-stream then expect to be able to set the iFrame source, but it's not working.

I can verify that the blob data is in fact being returned from the backend.

This is the JS code that uses the blob.

iframe.src = URL.createObjectURL(data);

EDIT 1:

I'm being asked to edit my question with why the suggested prior post doesn't solve my issue. Here's a copy/paste from my comments below:

I did see that post already and the accepted answer says: "Consider avoiding createObjectURL() method, while browsers are disabling support for it. Just attach MediaStream object directly to the srcObject property of HTMLMediaElement e.g. element." I'm not an expert with JavaScript but I don't think MediaStream will work.


EDIT 2:

Thanks to David Caldwell, in his comment he mentioned "src/srcObject"which made me look a little closer at the docs for MediaStream. I have something now that isn't erroring out. All I need is the correct Mime for the blob so I can use it in the iFrame src.

Here is what I have now that returns the srcObject:

var binaryData = [];
binaryData.push(data); //My blob
var foo = URL.createObjectURL(new Blob(binaryData, {type: "application/text"}));
console.log(foo); //gives me the correct object

Should I be using a Mime of "text"? I need to assign that object to the iFrame src.


EDIT3:

Using a MIME of text/plain, I get the following in the DOM:

<iframe id="iframe-target" src="blob:http://192.168.112.12/e25a4404-8233-44f0-86b3-1fff1109805f" width="100%" height="100%">
  #Document
  <html>
    <head></head>
    <body>
      <pre style="word-wrap: break-word; white-space: pre-wrap;">[object Object]</pre> <--'object Object' is the issue
    </body>
  </html>
</iframe>

I now see the blob object in the iframe but the HTML within the iframe is showing as an Object. The object is actually a PDF but as it is, I can't view it. I still think this is a MIME issue, but I'm not sure what to use.


I think you can still use Content-type: application/pdf on the response, the point is to receive a valid blob.

When creating the object URL, assuming data is still your blob, you should do:

var blobObj = new Blob([atob(data)], { type: "application/pdf" });
var url = window.URL.createObjectURL(blobObj);
document.getElementById("iframe-target").setAttribute("src", url);

Here, a few things are happening:

  • data is converted back to binary with atob()
  • this binary data is then passed as a byte array to the Blob() constructor
  • the Blob object is used with the MIME type to create the object URL
  • the resulting object URL can be used as the src attribute for an iframe

I've created a snippet as a small demo, here you can choose a local PDF file, which will be converted to base64, then used as the src attribute in an iframe. See the source code on CodeSandbox and see the demo of the sandbox here.


UPDATE: Removed embedded snippet.

As @K J pointed out in the comments, running the snippet embedded or from the CodeSandbox editor will produce errors.

At first glance, it appears that the browser blocks the resulting blob URL. This is because window.URL.createObjectURL prepends the blob URL differently based on the origin.

This isn't a problem in production, but makes demoing the solution a bit more difficult. Luckily, CodeSandbox deploys the app to a host, where the blob URL scheme and host will match the app URL: blob URL matches the host

In this case, the PDF will be shown as expected. I've tested the deployed version of the sandbox on Chrome, Safari, and Firefox.