打开保存对话框前先写入电子文件



我正在使用electronic开发一个应用程序。在完成一些加密操作后,我需要向用户显示一个对话框来保存文件。我想给文件的文件名是一个随机散列,但我也没有成功。我正在尝试使用此代码,但文件将不会保存。我该怎么解决这个问题?

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。因此,您不必传入回调函数,而是处理promise的解析。注意,这仅适用于Electron>=版本6。然而,如果你运行一个旧版本的Electron,你的代码将是正确的——但你真的应该更新到一个新版本(Electron v6早在一年多前就发布了(。

像下面这样调整代码可以作为解决问题的起点。但是,由于您没有说明如何生成哈希(hash.createHash从哪里来?;您忘记声明/导入hash了吗?您忘记传递任何消息字符串了吗?;您是否使用hash作为NodeJS的crypto模块的别名?(,(此时(无法调试为什么您没有从console.log (filename)获得任何输出(我认为您的意思是"在代码中,不会创建随机文件名"(。一旦你提供了更多关于这个问题的细节,我很乐意相应地更新这个答案。

至于默认文件名:根据Electron文档,您可以将文件路径传递到dialog.showSaveDialog (),为用户提供默认文件名。

您使用的文件类型扩展名实际上也应该与文件扩展名一起传递到保存对话框中。此外,将此文件扩展名作为过滤器传递到对话框中,将阻止用户选择任何其他文件类型,这最终也是您当前通过将其附加到文件名所做的。

此外,您可以使用CryptoJS生成文件名:给定一些任意字符串,这些字符串实际上可能是随机字节,您可以这样做:filename = CryptoJS.MD5 ('some text here') + '.mfs';然而,请记住明智地选择输入字符串。MD5已被破坏,因此不应再用于存储机密——使用任何已知信息对加密您存储的文件(如data.password(至关重要,这本身就是不安全的。关于如何在互联网上用JavaScript创建随机字符串,有一些很好的例子,以及SO.上的答案

考虑到所有这些问题,最终可能会出现以下代码:

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

最新更新