ElectronでFileのOpenとSave

ElectronでFileのOpenとSave:

Electronでファイル操作する必要があったのでOpenとSaveの方法をメモ。

dialogの制御方法が知りたいのが主目的なので、ロジックはなし。

csvを読み込み表示。そのままsaveする。


仕様

下記のような感じ。

  • openボタンを押すとファイオープンし、textareaに表示。
  • saveでtextarea内の内容をfileにSave。


スクリーンショット 2019-01-27 7.14.03.png


textarea内を変更しても内容はファイルには反映されない。それをやるにはVueとかReact使う。


実装


package.json

エンドポイントはmain.jsとしました。

package.json
{ 
  "name": "openclose", 
  "version": "1.0.0", 
  "description": "sample", 
  "main": "main.js", 
  "scripts": { 
    "start": "electron ." 
  }, 
  "devDependencies": { 
    "electron": "^4.0.2" 
  } 
} 


main.js

ElectronのQuick Startのmain.jsとほぼ一緒。

起動時の表示としてindex.htmlを呼び出している。

main.js
const { app, BrowserWindow } = require('electron') 
 
let win 
 
function createWindow() { 
 
    //ウインドウの作成 
    win = new BrowserWindow({ width: 800, height: 400 }) 
 
    //ウインドウに表示する内容 
    win.loadFile('index.html') 
 
    //デバッグ画面表示 
    // win.webContents.openDevTools() 
 
    //このウインドウが閉じられたときの処理 
    win.on('closed', () => { 
        win = null 
    }) 
} 
 
//アプリが初期化されたとき(起動されたとき) 
app.on('ready', () => { 
    createWindow() 
}) 
 
//全ウインドウが閉じられたとき 
app.on('window-all-closed', () => { 
    if (process.platform !== 'darwin') { 
        app.quit() 
    } 
}) 
 
//アクティブになったとき(MacだとDockがクリックされたとき) 
app.on('activate', () => { 
    if (win === null) { 
        createWindow() 
    } 
}) 


index.html

画面要素を配置。ロジックを実装するindex.jsとstyles.cssを呼び出している。

index.html
<!DOCTYPE html> 
<html> 
 
<head> 
    <meta charset="utf-8"> 
    <title>sample</title> 
    <link rel="stylesheet" href="styles.css"> 
</head> 
<body> 
    <h3>File Open/Save</h3> 
    <button id="openFile">Open</button> 
    <button id="saveFile">Save</button> 
    <br> 
    <textarea id="preview"></textarea> 
    <script src="index.js"></script> 
</body> 
</html> 


index.js

ここにいろいろ書く。やってることは、

  • OpenDialogで開くファイル名(Path)を取得し、その情報を利用してファイルをオープン。
  • SaveDialogで保存するファイル名(Path)を取得して、その情報を利用してファイルをSave。
index.js
const fs = require('fs'); 
const { BrowserWindow, dialog } = require('electron').remote; 
 
//html内の要素取得とリスナーの設定 
document.querySelector("#openFile").addEventListener('click', () => { 
    openFile(); 
}) 
 
document.querySelector("#saveFile").addEventListener('click', () => { 
    saveFile(); 
}) 
 
const preview = document.getElementById('preview'); 
 
//openFileボタンが押されたとき(ファイル名取得まで) 
function openFile() { 
    const win = BrowserWindow.getFocusedWindow(); 
    dialog.showOpenDialog( 
        win, 
        { 
            properties: ['openFile'], 
            filters: [ 
                { 
                    name: 'Document', 
                    extensions: ['csv', 'txt'] 
                } 
            ] 
        }, 
        (fileNames) => { 
            if (fileNames) { 
                // alert(fileNames[0]); 
                readFile(fileNames[0]); //複数選択の可能性もあるので配列となる。 
            } 
        } 
    ) 
} 
 
//指定したファイルを読み込む 
function readFile(path) { 
    fs.readFile(path, (error, data) => { 
        if (error != null) { 
            alert("file open error."); 
            return; 
        } 
        preview.textContent = data.toString(); 
    }) 
} 
 
//saveFileボタンが押されたとき 
function saveFile() { 
    const win = BrowserWindow.getFocusedWindow(); 
    dialog.showSaveDialog( 
        win, 
        { 
            properties: ['openFile'], 
            filters: [ 
                { 
                    name: 'Documents', 
                    extensions: ['csv', 'txt'] 
                } 
            ] 
        }, 
        (fileName) => { 
            if (fileName) { 
                const data = preview.textContent; 
                console.log(data); 
                writeFile(fileName, data); 
            } 
        } 
    ) 
} 
 
//fileを保存(Pathと内容を指定) 
function writeFile(path, data) { 
    fs.writeFile(path, data, (error) => { 
        if (error != null) { 
            alert("save error."); 
            return; 
        } 
    }) 
} 


styles.css

まあ、おまけ程度ですが、いちおう。

styles.css
#preview{ 
    margin-top: 20px; 
    width: 300px; 
    height: 100px; 
} 

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)