nodejs - 临时文件名

nor*_*gon 34 node.js

在node.js中,如何生成唯一的临时文件名,la mkstemp(3)?我想用原子方式写一个文件fs.rename.

Ste*_*sen 41

另一个受欢迎的包是tmp.

  • 为什么这是真正的答案? (21认同)
  • 这才是真正的答案 (4认同)

Mar*_*arc 23

也许你已经在此期间找到了node-temp.


kin*_*tic 15

不使用任何其他插件:

var crypto = require('crypto');
var fs = require('fs'); 

var filename = 'foo'+crypto.randomBytes(4).readUInt32LE(0)+'bar';
fs.writeFileSync(filename, 'baz');
Run Code Online (Sandbox Code Playgroud)

编辑:阅读评论.

  • 小心,这是一个非常危险的经典反模式!这种代码多年来导致了许多漏洞,并且正是为了取代mktemp而创建mkstemp的确切原因.为了安全起见,应该使用O_CREAT和O_EXCL标志打开文件,以防止其他用户在写入文件名之前预测文件名并创建符号链接.我想如果你完全确定另一个用户无法在一百万年内预测文件名,那就没有必要,但为什么有机会呢?http://en.wikipedia.org/wiki/Symlink_race (40认同)
  • 鉴于其他2个答案建议安装在安装时运行任意代码的任意代码,随着时间的推移随意改变,取决于其他几个软件包并且可怕的过度工程,无论如何这种方法更好. (6认同)
  • Josue,我同意32位熵太少了.但是,对于短期文件,64位应该足够了.如果我们已经有一个随机值,你为什么建议哈希? (3认同)
  • 我认为该文件名中没有足够的熵,它输出`foo1492796329bar`一个带有随机盐的SHA1会更好 (2认同)

Eri*_*sty 12

在 Node 和 Python 中创建临时文件会受到涉及权限更改和跨平台问题的竞争条件的影响,尤其是在 Windows 上,测试 ACL 具有挑战性。

结果是,它实际上可以挂起您的计算机,要求提供许多现代语言的临时文件。(如果节点无权访问临时目录,根据 ACL,即使文件不存在,它也可以获得 EEXIST - 其结果可能是无限循环。)。

最简单的解决方案是使用足够的熵,使碰撞的可能性可以忽略不计(在密码学意义上)。

这还有一个副作用,即可以在所有平台上安全地创建临时文件,而无需严格审查源代码。只要您的随机数是安全的,就无法预测将用于篡夺权限或访问的文件。

它有助于需要传递文件名而不是文件句柄的程序。

const crypto = require('crypto');
const os = require('os'); 
const path = require('path'); 

function tmpFile(prefix, suffix, tmpdir) {
    prefix = (typeof prefix !== 'undefined') ? prefix : 'tmp.';
    suffix = (typeof suffix !== 'undefined') ? suffix : '';
    tmpdir = tmpdir ? tmpdir : os.tmpdir();
    return path.join(tmpdir, prefix + crypto.randomBytes(16).toString('hex') + suffix);
}
Run Code Online (Sandbox Code Playgroud)

唯一的缺点是这不适用于 FAT 格式的分区,而 FAT 格式的分区在 U 盘上仍然很常见。


Fer*_*jal 7

试试这个功能,安全无漏洞。节点 8.x LTS

function tempFile (name = 'temp_file', data = '', encoding = 'utf8') {
    const fs = require('fs');
    const os = require('os');
    const path = require('path');

    return new Promise((resolve, reject) => {
        const tempPath = path.join(os.tmpdir(), 'foobar-');
        fs.mkdtemp(tempPath, (err, folder) => {
            if (err) 
                return reject(err)

            const file_name = path.join(folder, name);

            fs.writeFile(file_name, data, encoding, error_file => {
                if (error_file) 
                    return reject(error_file);

                resolve(file_name)
            })
        })
    })
}
Run Code Online (Sandbox Code Playgroud)

它解析临时文件的 PATH,拒绝 mkdtemp 或 writeFile 错误

// C:\Users\MYPC\AppData\Local\Temp\foobar-3HmKod\temp_file
// /temp/Temp/foobar-3HmKod/temp_file
tempFile().then(path => console.log(path)).catch(e => console.log("error", e)) //or

// C:\Users\MYPC\AppData\Local\Temp\foobar-9KHuxg\hola.txt
// /temp/Temp/foobar-9KHuxg/hola.txt
tempFile('hola.txt', 'hello there').then(path => console.log(path)).catch(e => console.log("e", e))
Run Code Online (Sandbox Code Playgroud)

  • 如果没有一些严肃的支持,声称该代码“安全且没有漏洞”是没有道理的。 (19认同)

mpe*_*pen 6

与kinematic 的答案类似,但有 2 个字节的额外熵和字母而不是数字:

import Crypto from 'crypto';
import {tmpdir} from 'os';
import Path from 'path';

function tmpFile(ext) {
    return Path.join(tmpdir(),`archive.${Crypto.randomBytes(6).readUIntLE(0,6).toString(36)}.${ext}`);
}
Run Code Online (Sandbox Code Playgroud)

用法:

const file = tmpFile('tar.gz'); // "/tmp/archive.1scpz5ew5d.tar.gz"
Run Code Online (Sandbox Code Playgroud)

我正在创建档案,所以我选择“archive”作为基本名称,但您可以根据需要更改它。