簡體   English   中英

Electron - 在打開保存對話框之前寫入文件

[英]Electron - write file before open save dialog

我正在使用 electron 開發應用程序。 完成一些加密操作后,我需要向用戶顯示一個對話框來保存文件。 我想給文件的文件名是隨機的 hash 但我也沒有成功。 我正在嘗試使用此代碼,但不會保存文件。 我該如何解決這個問題?

const downloadPath = app.getPath('downloads')

ipcMain.on('encryptFiles', (event, data) => {
  let output = [];
  const password = data.password;
  data.files.forEach( (file) => {
    const buffer = fs.readFileSync(file.path);
    const dataURI = dauria.getBase64DataURI(buffer, file.type);
    const encrypted = CryptoJS.AES.encrypt(dataURI, password).toString();
    output.push(encrypted);
  })
  const filename = hash.createHash('md5').toString('hex');
  console.log(filename)
  const response = output.join(' :: ');
  dialog.showSaveDialog({title: 'Save encrypted file', defaultPath: downloadPath }, () => {
    fs.writeFile(`${filename}.mfs`, response, (err) => console.log(err) )  
  })
})

您遇到的問題是由 Electron 的 UI 函數的異步特性引起的:它們不采用回調函數,而是返回 Promise。 因此,您不必傳入回調 function,而是處理 promise 的解析。 請注意,這僅適用於 Electron >= 版本 6。但是,如果您運行的是 Electron 的舊版本,您的代碼將是正確的——但是您應該真正更新到較新的版本(電子 v6 已在一年前發布) .

像下面這樣調整您的代碼可以成為解決問題的起點。 However, since you do not state how you generate the hash (where does hash.createHash come from?; did you forget to declare/import hash ?; did you forget to pass any message string?; are you using hash as an alias for NodeJS的crypto模塊?),(此時)無法調試為什么你沒有從console.log (filename)中得到任何output(我假設你的意思是“在代碼中,隨機文件名不會被創建")。 一旦您提供有關此問題的更多詳細信息,我很樂意相應地更新此答案。

至於默認文件名:根據Electron 文檔,您可以將文件路徑傳遞給dialog.showSaveDialog ()為用戶提供默認文件名。

您使用的文件類型擴展名實際上也應該與文件擴展名一起傳遞到保存對話框中。 同樣將此文件擴展名作為過濾器傳遞到對話框中將阻止用戶選擇任何其他文件類型,這最終也是您當前正在執行的操作,方法是將其附加到文件名中。

此外,您可以使用 CryptoJS 生成文件名:給定一些任意字符串,這實際上可能是隨機字節,您可以這樣做: filename = CryptoJS.MD5 ('some text here') + '.mfs'; 但是,請記住明智地選擇輸入字符串。 MD5 已被破壞,因此不應再用於存儲機密 - 使用任何對您存儲的文件加密至關重要的已知信息(例如data.password )本質上是不安全的。 有一些關於如何在互聯網上的 JavaScript 中創建隨機字符串的很好的例子,以及這里的答案

考慮到所有這些問題,最終可能會得到以下代碼:

const downloadPath = app.getPath('downloads'),
      path = require('path');

ipcMain.on('encryptFiles', (event, data) => {
  let output = [];
  const password = data.password;

  data.files.forEach((file) => {
    const buffer = fs.readFileSync(file.path);
    const dataURI = dauria.getBase64DataURI(buffer, file.type);
    const encrypted = CryptoJS.AES.encrypt(dataURI, password).toString();
    output.push(encrypted);
  })

  // not working:
  // const filename = hash.createHash('md5').toString('hex') + '.mfs';

  // alternative requiring more research on your end
  const filename = CryptoJS.MD5('replace me with some random bytes') + '.mfs';
  console.log(filename);

  const response = output.join(' :: ');
  dialog.showSaveDialog(
    {
      title: 'Save encrypted file',
      defaultPath: path.format ({ dir: downloadPath, base: filename }), // construct a proper path
      filters: [{ name: 'Encrypted File (*.mfs)', extensions: ['mfs'] }] // filter the possible files
    }
  ).then ((result) => {
    if (result.canceled) return; // discard the result altogether; user has clicked "cancel"
    else {
      var filePath = result.filePath;
      if (!filePath.endsWith('.mfs')) {
        // This is an additional safety check which should not actually trigger.
        // However, generally appending a file extension to a filename is not a
        // good idea, as they would be (possibly) doubled without this check.
        filePath += '.mfs';
      }
      fs.writeFile(filePath, response, (err) => console.log(err) )  
    }
  }).catch ((err) => {
    console.log (err);
  });
})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM