简体   繁体   English

Electron - 在打开保存对话框之前写入文件

[英]Electron - write file before open save dialog

I'm using electron to develop an app.我正在使用 electron 开发应用程序。 after some encryption operations are done, I need to show a dialog to the user to save the file.完成一些加密操作后,我需要向用户显示一个对话框来保存文件。 The filename I want to give to the file is a random hash but I have no success also with this.我想给文件的文件名是随机的 hash 但我也没有成功。 I'm trying with this code but the file will not be saved.我正在尝试使用此代码,但不会保存文件。 How I can fix this?我该如何解决这个问题?

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) )  
  })
})

The problem you're experiencing is resulting from the asynchronous nature of Electron's UI functions: They do not take callback functions, but return promises instead.您遇到的问题是由 Electron 的 UI 函数的异步特性引起的:它们不采用回调函数,而是返回 Promise。 Thus, you do not have to pass in a callback function, but rather handle the promise's resolution.因此,您不必传入回调 function,而是处理 promise 的解析。 Note that this only applies to Electron >= version 6. If you however run an older version of Electron, your code would be correct -- but then you should really update to a newer version (Electron v6 was released well over a year ago).请注意,这仅适用于 Electron >= 版本 6。但是,如果您运行的是 Electron 的旧版本,您的代码将是正确的——但是您应该真正更新到较新的版本(电子 v6 已在一年前发布) .

Adapting your code like below can be a starting point to solve your problem.像下面这样调整您的代码可以成为解决问题的起点。 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 module?), it is (at this time) impossible to debug why you do not get any output from console.log (filename) (I assume you mean this by "in the code, the random filename will not be created"). 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(我假设你的意思是“在代码中,随机文件名不会被创建")。 Once you provide more details on this problem, I'd be happy to update this answer accordingly.一旦您提供有关此问题的更多详细信息,我很乐意相应地更新此答案。

As for the default filename: As per the Electron documentation , you can pass a file path into dialog.showSaveDialog () to provide the user with a default filename.至于默认文件名:根据Electron 文档,您可以将文件路径传递给dialog.showSaveDialog ()为用户提供默认文件名。

The file type extension you're using should also actually be passed with the file extension into the save dialog.您使用的文件类型扩展名实际上也应该与文件扩展名一起传递到保存对话框中。 Also passing this file extension as a filter into the dialog will prevent users from selecting any other file type, which is ultimately what you're also currently doing by appending it to the filename.同样将此文件扩展名作为过滤器传递到对话框中将阻止用户选择任何其他文件类型,这最终也是您当前正在执行的操作,方法是将其附加到文件名中。

Also, you could utilise CryptoJS for the filename generation: Given some arbitrary string, which could really be random bytes, you could do: filename = CryptoJS.MD5 ('some text here') + '.mfs';此外,您可以使用 CryptoJS 生成文件名:给定一些任意字符串,这实际上可能是随机字节,您可以这样做: filename = CryptoJS.MD5 ('some text here') + '.mfs'; However, remember to choose the input string wisely.但是,请记住明智地选择输入字符串。 MD5 has been broken and should thus no longer be used to store secrets -- using any known information which is crucial for the encryption of the files you're storing (such as data.password ) is inherently insecure. MD5 已被破坏,因此不应再用于存储机密 - 使用任何对您存储的文件加密至关重要的已知信息(例如data.password )本质上是不安全的。 There are some good examples on how to create random strings in JavaScript around the internet, along with this answer here on SO.有一些关于如何在互联网上的 JavaScript 中创建随机字符串的很好的例子,以及这里的答案

Taking all these issues into account, one might end up with the following code:考虑到所有这些问题,最终可能会得到以下代码:

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