X Builder
X Builder

Reputation: 240

How to read a local file in Javascript (Running from an Electron App)

How can I read the text from a local file using a plain file URL in JavaScript?

I’ve found plenty of examples for reading files via the HTML file input tag, but I’m struggling to find a straightforward example of accessing a file on my PC using plain JavaScript. This will be for an Electron application.

I need a code example, such as:

readFile("file:\\\\C:\\path\\to\\file.txt", "text/plain");

readFile(url, mimetype) {
    // Implementation here
}

Upvotes: 10

Views: 18723

Answers (4)

RAVIKUMAR PAWAR
RAVIKUMAR PAWAR

Reputation: 111

async readFileContent(filePath) {
    try {
        const response = await fetch(filePath);
        if (!response.ok) throw new Error(`Failed to fetch file: ${response.statusText}`);
        const text = await response.text();
        console.log('file content:', text);
    } catch (error) {
        console.error(`Error loading file: ${error.message}`);
    }
}

Upvotes: 0

Patrick X
Patrick X

Reputation: 32

  1. Reading a file is done using node and is not dependent on electron
  2. Where you have the code for creating a window add this code
const fs = require("fs");

function readFile(fileURL,mimeType){
   //readfile does not accept the file:\\\ thing, so we remove it
   const pathToFile = fileURL.replace("file:\\\\",'');

   fs.readFile(pathToFile,mimeType,(err,contents)=>{
     if(err){
        console.log(err);
        return;
     }
     console.log(contents);
   })
}

readFile('C:\\Users\\<userAccount>\\Documents\\test.txt','utf8')
//If your on windows you'll need to use double backslashes for the paths
//here's an example regex to do that

pathToFile = pathToFile.replace(/\\/,'\\\\')

Upvotes: 0

reZach
reZach

Reputation: 9429

If you want to read a file in Electron, you have to understand the various parts of an Electron app. In short, there is a main process and a renderer process. The main process has and is given all control to use node modules, such as the fs module that can read files. The renderer process should not have access to the fs module, but instead anytime it needs to use the fs module, it should ask the main process to use fs, and then return the result.

FYI the renderer process is the web page, the visible part of your Electron app.

This communication is called IPC (inter-process communication). The flow is:

  1. Renderer process sends a message to the main process over IPC
  2. The main process hears the message, and then reads a file with fs
  3. The contents/result are sent back via IPC to the renderer process
  4. The renderer process now can do what it wants with the data from the file

A very rough example is below.

index.html

<!doctype html>
<html lang="en-US">
<head>
    <meta charset="utf-8"/>
    <title>Title</title>
</head>
<body>
    <script>
        // Called when message received from main process
        window.api.receive("fromMain", (data) => {
            console.log(`Received ${data} from main process`);
        });

        // Send a message to the main process
        window.api.send("toMain", "some data");
    </script>
</body>
</html>

main.js

const {
  app,
  BrowserWindow,
  ipcMain
} = require("electron");
const path = require("path");
const fs = require("fs");

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win;

async function createWindow() {

  // Create the browser window.
  win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: false, // is default value after Electron v5
      contextIsolation: true, // protect against prototype pollution
      enableRemoteModule: false, // turn off remote
      preload: path.join(__dirname, "preload.js") // use a preload script
    }
  });

  // Load app
  win.loadFile(path.join(__dirname, "dist/index.html"));

  // rest of code..
}

app.on("ready", createWindow);

ipcMain.on("toMain", (event, args) => {
  fs.readFile("path/to/file", (error, data) => {
    // Do something with file contents

    // Send result back to renderer process
    win.webContents.send("fromMain", responseObj);
  });
});

preload.js

const {
    contextBridge,
    ipcRenderer
} = require("electron");

// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld(
    "api", {
        send: (channel, data) => {
            // whitelist channels
            let validChannels = ["toMain"];
            if (validChannels.includes(channel)) {
                ipcRenderer.send(channel, data);
            }
        },
        receive: (channel, func) => {
            let validChannels = ["fromMain"];
            if (validChannels.includes(channel)) {
                // Deliberately strip event as it includes `sender` 
                ipcRenderer.on(channel, (event, ...args) => func(...args));
            }
        }
    }
);

DISCLAIMER: I'm the author of a popular secure electron template, and have wrote a specific guide on how to use fs to read a file in an Electron app. I hope you give it a read because it has additional information there.

Upvotes: 25

AlignSD
AlignSD

Reputation: 21

if im not mistaken, using something like this should work with the fs module.

fs.readFileSync("/path/to/file.txt");

Upvotes: -3

Related Questions