6

Scenario

I'm contributing for a OSS project that is build on BlazorServerSide and ElectronNET.API Version 9.31.1.

In an Electron window we would like to show images from local storage UI via <img> tag.

What I have tried:

I have tried with:

<img src="file:///home/dani/pictures/someimage.jpg" />

But doesn't work. Image doesn't appear. I have then tried to create electron window with WebSecurity = false, but also doesn't help (images appears as broken on UI):

var browserWindowOptions = new BrowserWindowOptions
{
    WebPreferences = new WebPreferences
    {
        WebSecurity = false,
    },
};

Task.Run(async () => await Electron.WindowManager.CreateWindowAsync(
    browserWindowOptions,
    $"http://localhost:{BridgeSettings.WebPort}/Language/SetCultureByConfig"
));

Finally, as workaround, I'm sending the images as data base64 in img src's attribute, but it looks like a dirty approach.

My Question:

My question is, how can I show on electron window picture files from local storage.

Some irrelevant info:

The open source line where I need assistance.

dani herrera
  • 48,760
  • 8
  • 117
  • 177
  • 1
    I also get `Not allowed to load local resource: file:///path/to/file.png` in console. – dobson Jul 20 '20 at 23:00
  • Thanks @dobson, appreciate. – dani herrera Jul 21 '20 at 09:12
  • 1
    Did you check this answer? https://stackoverflow.com/a/50319258/13956032 – saraserin Jul 21 '20 at 10:59
  • Hi @saraserin, I did. Answer talks about _you can disable websecurity during development_ and I also tried it unsuccessfully. Thanks about your comment. – dani herrera Jul 21 '20 at 11:30
  • This is almost certainly a duplicate of https://stackoverflow.com/questions/50272451/electron-js-images-from-local-file-system but because of your bounty, folks can't recommend to close as duplicate. Still: check that post, because you should not be using `file:///` URLs. And if you have data in localStorage, make sure that's in data-url format so you can just directly use that? – Mike 'Pomax' Kamermans Jul 21 '20 at 23:06

1 Answers1

0

There are several ways to go about this, so I will try to cover the most relevant use cases. Some of this depends on the context of your project.

Access to local files behave as cross origin requests by default. You could try using the crossorigin=anonymous attribute on your image tag, but doesn't work because your local file system will not be responding with cross origin headers.

Disabling the webSecurity option is a workaround, but is not recommended for security reasons, and will not usually work correctly anyway if your html is not also loaded from the local file system.

Disabling webSecurity will disable the same-origin policy and set allowRunningInsecureContent property to true. In other words, it allows the execution of insecure code from different domains.

https://www.electronjs.org/docs/tutorial/security#5-do-not-disable-websecurity

Here are some methods of working around this issue:

1 - Use the HTML5 File API to load local file resources and provide the ArrayBuffer to ImageData to write the image to a <canvas> .

function loadAsUrl(theFile) {
    var reader = new FileReader();

    var putCanvas = function(canvas_id) {
      return function(loadedEvent) {
        var buffer = new Uint8ClampedArray(loadedEvent.target.result);
        document.getElementById(canvas_id)
                .getContext('2d')
                .putImageData(new ImageData(buffer, width, height), 0, 0);
      }
    }

    reader.onload = putCanvas("canvas_id");

    reader.readAsArrayBuffer(theFile);
}

1.b - It is also possible to load a file as a data URL. A data URL can be set as source (src) on img elements with JavaScript. Here is a JavaScript function named loadAsUrl() that shows how to load a file as a data URL using the HTML5 file API:

function loadAsUrl(theFile) {
    var reader = new FileReader();

    reader.onload = function(loadedEvent) {
        var image = document.getElementById("theImage");
        image.setAttribute("src", loadedEvent.target.result);
    }

    reader.readAsDataURL(theFile);
}

2 - Use the Node API fs to read the file, and convert it into a base64 encoded data url to embed in the image tag.

Hack - Alternatively you can try loading the image in a BrowserView or <webview>. The former overlays the content of your BrowserWindow while the latter is embedded into the content.

// In the main process.
const { BrowserView, BrowserWindow } = require('electron')

const win = new BrowserWindow({ width: 800, height: 600 })

const view = new BrowserView()
win.setBrowserView(view)
view.setBounds({ x: 0, y: 0, width: 300, height: 300 })
view.webContents.loadURL('file:///home/dani/pictures/someimage.jpg')
NeoVance
  • 404
  • 2
  • 9
  • Thanks about your answer, it looks for electron but not for Electron.Net+Blazor. Your solution is the workaround I talk in question. – dani herrera Jul 22 '20 at 06:06