Select and display an image from the filesystem with electron
Asked Answered
B

5

15

I'm developing a little app in Electron from which I can upload an image to Instagram and I'm stuck at one of the first steps :/

I want to select an image from the filesystem and display it in my app.

This is the code I've got so far:

CODE:

remote.dialog.showOpenDialog((filenames) => {
    fs.readFile(filepath, 'utf-8', (err, data) => {

        if(err){
            alert("An error ocurred reading the file :" + err.message);
            return;
        }
    });
});
Bithia answered 10/6, 2018 at 8:6 Comment(0)
G
20

A minimal example to select, read and display a png image.

Renderer process:::

var remote = require('electron').remote;
var fs = remote.require('fs');

  
remote.dialog.showOpenDialog(remote.getCurrentWindow(),
   {
    filters: [
      {name: 'Images', extensions: ['png']}
    ]
   }, 
   function(filepaths, bookmarks) {
     //read image (note: use async in production)
     var _img = fs.readFileSync(filepaths[0]).toString('base64');
     //example for .png
     var _out = '<img src="data:image/png;base64,' + _img + '" />';
     //render/display
     var _target = document.getElementById('image_container');
     _target.insertAdjacentHTML('beforeend', _out);

     return;
});
<div id="image_container"></div>
Garlaand answered 11/6, 2018 at 8:9 Comment(3)
Thanks, I ended up using this line fs.readFileSync(filepaths[0]).toString('base64') I can build further from there.Bithia
There is a way to attach file buffer directly to image ? without convert it to base64Balneal
document is not definedBairam
F
17

Here is a solution with more information on separation of main process and renderer and usage of es6

main process

import { ipcMain, dialog } from "electron";
import fs from 'fs';

ipcMain.on("chooseFile", (event, arg) => {
  const result = dialog.showOpenDialog({
    properties: ["openFile"],
    filters: [{ name: "Images", extensions: ["png","jpg","jpeg"] }]
  });

  result.then(({canceled, filePaths, bookmarks}) => {
    const base64 = fs.readFileSync(filePaths[0]).toString('base64');
    event.reply("chosenFile", base64);
  });
});

renderer process

import electron from 'electron';

// trigger file prompt
electron.ipcRenderer.send('chooseFile');

// handle response
electron.ipcRenderer.on('chosenFile', (event, base64) => {
  const src = `data:image/jpg;base64,${base64}`
})
Freemasonry answered 16/2, 2020 at 17:50 Comment(2)
thanks. this was way more relatable and understandable for meVedic
use handle/invoke instead of on/send will make it more clearSpleen
F
8

With electron 11 the following snippet from https://www.electronjs.org/docs/api/protocol works

app.whenReady().then(() => {
  protocol.registerFileProtocol('atom', (request, callback) => {
    console.log(request.url)
    const url = request.url.substr(7)
    callback({ path: url })
  })
})

Be careful not to use the usual file:// protocol, but the custom 'atom' or 'my_whatever' protocol instead

You can now get the image this way :

<img src="atom://C:\\Users\\my_path\\myfile.png" />

However if you wan't to keep the syntaxe of the file protocol in the render side, you can do the following :

protocol.registerFileProtocol('file', ()=>...)

Now you can get an image this way

<img src="file://C:\\Users\\my_path\\myfile.png" />

However you will have to disable webSecurity

const mainWindow = new BrowserWindow({
webPreferences: {
  nodeIntegration : true,
  webSecurity: false
}
Fraenum answered 30/1, 2021 at 17:18 Comment(1)
This is a way better solution👌Caucasoid
O
0

By default, the file:// protocol is disabled. As such, you must register your own protocol. Thanks to nicoNx for his answer which included the link to the electron protocol docs. The following code is a direct copy from the Electron docs: https://www.electronjs.org/docs/latest/api/protocol

const { app, protocol } = require('electron')
const path = require('path')
const url = require('url')

app.whenReady().then(() => {
  protocol.registerFileProtocol('atom', (request, callback) => {
    const filePath = url.fileURLToPath('file://' + request.url.slice('atom://'.length))
    callback(filePath)
  })
})

Then in your html:

<img src="atom://[FILE_ADDRESSS]" />

If your experience problems, make sure you are attaching the protocol to the correct browser session. You can find more details on how to manage your browser sessions in the electron protocol docs (link above). Also make sure you register the protocol "after" the app is ready.

Overlook answered 3/4, 2023 at 7:26 Comment(0)
S
0

set webSecurity to false in your browserwindow settings.

  mainWindow = new BrowserWindow({
      ...your prev settings
    webPreferences: {
      ...your prev settings
      webSecurity: false, // to load local imgs
   }
  });

Then in your renderer you can put src as path.join('file://', ${ur local image path}) and it will work.

Shufu answered 19/1 at 19:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.