如何保存文件并将其读入缓冲区? (错误 - 缓冲区为空)

Posted

技术标签:

【中文标题】如何保存文件并将其读入缓冲区? (错误 - 缓冲区为空)【英文标题】:How to save a file and read it into a buffer? (error - buffer is empty) 【发布时间】:2019-11-26 06:10:57 【问题描述】:

我需要从 url (pdf) 中获取文件并保存它们,然后存储在使用缓冲区的备用文件系统中。我发现的是 url 的 get 工作,文件保存在本地,但是当我尝试获取缓冲区时,它是空的。

当我在文件已保存的情况下第二次运行时,它确实可以工作。我认为这与以某种方式关闭文件有关。有人有什么想法吗?我的代码如下 -

功能保存文件(文件名,网址) 常量文件 = fs.createWriteStream(文件名); 常量请求 = https.get(url, function(response) response.pipe(文件); console.log("文件保存"); 返回文件; );; app.post('/addfile', function(req, res) var 文件名 = req.body.filename; var url = req.body.url; var 文件 = 保存文件(文件名,网址); 让 testFile = fs.readFileSync(filename); 让 testBuffer = new Buffer(testFile); // 处理测试缓冲区

【问题讨论】:

【参考方案1】:

我认为这里的问题是当你调用 savefile 时,它​​在数据被读取并保存到磁盘之前返回。

这意味着当您调用 fs.readFileSync 时,文件数据尚不存在。在文件出现之前可能需要几百毫秒。请记住 https.get 函数是阻塞的(就像 Node.js 中的大多数 I/O 函数一样)。

因此,最好的方法是使用回调函数来指示我们何时完成,或者使用 Promise。我通常更喜欢后者,因为代码语法更清晰。

例如(带有承诺):

function savefileWithPromise(filename, url) 
    return new Promise((resolve, reject) => 

        // Create file and setup close handler.
        const file = fs.createWriteStream(filename)
            .on('close', () => resolve("File end"));

        // Read data from url..the file.close handler will fire when the response has been piped to the file stream.
        https.get(url, function(response) 
            response.pipe(file);
        );
    );


app.post('/addfile', async function(req, res) 
    var filename = req.body.filename;
    var url = req.body.url;
    console.log(`/addfile: Reading from url: $url, writing to file $filename...`);
    await savefileWithPromise(filename, url);
    // readFileSync returns a buffer.
    let testFile = fs.readFileSync(filename);
    console.log("File length: " + testFile.length + " byte(s).")
    res.status(200).send("ok");
);

我们也可以用回调做同样的事情:

function savefileWithCallback(filename, url, callback) 
    // Create file and setup close handler.
    const file = fs.createWriteStream(filename)
        .on('close', () => callback("File end"));

    // Read data from url..
    https.get(url, function(response) 
        response.pipe(file);
    );


app.post('/addfile', function(req, res) 
    var filename = req.body.filename;
    var url = req.body.url;
    console.log(`/addfile: Reading from url: $url, writing to file $filename...`);
    savefileWithCallback(filename, url, function() 
        // readFileSync returns a buffer.
        let testFile = fs.readFileSync(filename);
        console.log("File length: " + testFile.length + " byte(s).")
        res.status(200).send("ok");
    );
);

然后将 url 数据简单地读取到缓冲区:

function readUrlDataToBuffer(url) 
    return new Promise((resolve, reject) => 
        https.get(url, function(response) 
            const data = [];
            response.on('data', function(chunk) 
                data.push(chunk);
            ).on('end', function() 
                resolve(Buffer.concat(data));
            )
        ).on('error', function(err) 
            reject(err);
        );
    );


app.post('/addfile', async function(req, res) 
    try 
        var url = req.body.url;
        console.log(`/addfile: Reading from url: $url..`);
        let buffer = await readUrlDataToBuffer(url);
        console.log("Buffer length: " + buffer.length + " byte(s).");
        res.send('ok');
     catch (error) 
        res.status(500).send('An error occurred');
    
);

【讨论】:

我使用 await 得到这个 - 我之前尝试过 await,我只是再次尝试 - await savefilWithPromise(filename, url); ^^^^^ SyntaxError: await 仅在异步函数中有效 哦,是的,那个老东西.. 是后处理程序异步,例如app.post('/addfile', async function(req, res) ? Ta! 一切正常!杰出的。另外,我们真的可以获取 url 内容并将其直接推送到缓冲区中,然后甚至不使用文件吗?由于各种代码片段的一些拼凑,我有一个文件。无论如何,我会将其标记为完成。 我现在已经添加了将url数据直接读取到缓冲区的代码! 一切正常。又是天才之作。对于其他人,我测试了缓冲区,并用 promise 保存 - 而不是回调(因为其他人已经工作了)。

以上是关于如何保存文件并将其读入缓冲区? (错误 - 缓冲区为空)的主要内容,如果未能解决你的问题,请参考以下文章

如何将文件内容读入 istringstream?

C getline() - 如何处理缓冲区/如何将未知数量的值读入数组

sed

如何保存帧缓冲区然后将其取回

读-处理-写的最佳缓冲区大小

Windows C++ API:如何将整个二进制文件读入缓冲区?