Using a Blob as iframe source and a trouble with loading img src images located in a subdirectory

EDIT: I added live version of the issue here: https://www.lieksa.info/demot/stackoverflow/blob_issue/problem.html

I am trying to use Javascript to preview images inside an iFrame to show the user how the image looks like. The images are located in a subdirectory, for example: "kuvat/kuva0.jpg".

If a user presses "preview" button, I take the generated html data (html source data in a string format) and turn it into a Blob object and use that as a iframe source for preview.

The generated html and images itself does work, if for example copy-pasted in to a new .html file and displayd via there. Images and everything display nicely.

The problem is that the images in the subdirectory and referenced using "src" inside img html-tag are not working after conversion into iFrame source. What happens to the image source paths and references during the Blob and URL.createObjectURL(blob) process?

Generated html source code includes images in the following way

<img src="kuvat/kuva0.jpg" alt="slideshow image">

Below is the Blob and iframe process:

var html_source = document.getElementById("source_container").value;
var blob = new Blob([html_source], {type: "text/html"});
document.getElementById("iframe_container").src = URL.createObjectURL(blob);

I even tried only to pass only the image tag in to Blob object and also test a File object. But neither of them worked:

var blob = new Blob(['<img src="kuvat/kuva0.jpg" alt="slideshow image">'], {type: "text/html"});
var file = new File(['<img src="kuvat/kuva0.jpg" alt="slideshow image">'], "index.html", { type: "text/plain"});

document.getElementById("preview_container").src = URL.createObjectURL(blob);
// or
document.getElementById("preview_container").src = URL.createObjectURL(file);

Upvotes: 1

Views: 4733

Answers (1)

Kaiido
Kaiido

Reputation: 137131

The problem is that your iframe's document's baseURI is set to blob:https://www.lieksa.info/[UUID].

So when the browser will try to resolve the relative path of the image, it will use that baseURI to resolve it, resulting in an invalid URI:

const http_base = "https://www.lieksa.info/[UUID]";
console.log( 'http:', new URL( "kuva1.jpg", http_base ) ); // Success

const blob_base = "blob:https://www.lieksa.info/[UUID]";
console.log( 'blob:', new URL( "kuva1.jpg", blob_base ) ); // Error

To fix that, you can append a <base> element in the head of your document, before the <img> gets declared, this will set the correct baseURI for your document and the browser will be able to parse your relative path correctly:

const frame = document.getElementById('frame');
const html_content = `<!DOCTYPE html>
<html>
<head>
  <title>Test relative URI in blob:// frame</title>
  <!-- here we set the baseURI of our document -->
  <base href="https://upload.wikimedia.org/wikipedia/commons/4/47/">
</head>
<body>
  <!-- here we can use relative URIs, as if we were really on wikimedia's page -->
  <img src="PNG_transparency_demonstration_1.png" width="300">
</body>
</html>`;
const blob = new Blob( [html_content], { type: "text/html" } );
frame.src = URL.createObjectURL( blob );
<iframe id="frame"></iframe>

Upvotes: 5

Related Questions