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

时间:2019-07-17 12:01:05

标签: node.js

我需要从url(pdfs)中获取文件,将其保存,然后存储在使用缓冲区的备用文件系统中。我找到的是该网址的get方法,该文件保存在本地,但是当我尝试获取缓冲区时,它为空。

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

function savefile(filename, url) {

    const file = fs.createWriteStream(filename);
    const request = https.get(url, function(response) {
      response.pipe(file);
            console.log("file saved");
            return file;
    });;
}

app.post('/addfile', function(req, res) {

    var filename = req.body.filename;
    var url = req.body.url;
    var file = savefile(filename, url);
    let testFile = fs.readFileSync(filename);
    let testBuffer = new Buffer(testFile);
    // process testBuffer

1 个答案:

答案 0 :(得分:1)

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

这意味着当您调用fs.readFileSync时,文件数据尚不存在。该文件可能还需要几百毫秒的时间。请记住,https.get函数是 not 阻止的对象(就像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');
    }
});