Nodejs新人求助:我通过微信接口获取客户发送的大图片(HTTP流通过data事件分批发送),为啥用fs.appendFile经常发生图片花的情况?

Nodejs新人求助:我通过微信接口获取客户发送的大图片(HTTP流通过data事件分批发送),为啥用fs.appendFile经常发生图片花的情况?

新人求助:我通过微信接口获取客户发送的大图片(HTTP流通过data事件分批发送),为啥用fs.appendFile经常发生图片花的情况?

同一张图片当多个data的数据同时写入这个文件的时候,图片就会花掉

 resHttps.on('data', function (body) {

fs.appendFile(filePath, body, “utf8”, function (err) {

是不是要用同步才行?

原图

花图1

花图2


10 回复

针对你提到的问题,使用 fs.appendFile 方法可能会导致数据写入不完整或交错,从而导致图片损坏。这是因为 fs.appendFile 是异步操作,并且可能在多个数据片段到达时并发执行,导致数据混乱。

为了确保数据正确地写入文件,可以使用可写流(Writable Stream)来处理数据流。这样可以确保数据按顺序被正确写入文件中。下面是一个示例代码,展示如何使用可写流来处理大图片的下载:

const https = require('https');
const fs = require('fs');

// 创建一个可写流,用于将数据写入文件
const writeStream = fs.createWriteStream(filePath);

resHttps.on('data', function (chunk) {
    // 将数据片段写入可写流
    writeStream.write(chunk);
});

resHttps.on('end', function () {
    // 当所有数据都接收完毕后,关闭写入流
    writeStream.end();
    console.log('图片下载完成');
});

解释

  1. 创建可写流:使用 fs.createWriteStream(filePath) 创建一个可写流,该流会将数据写入指定路径的文件。
  2. 监听 ‘data’ 事件:当接收到数据片段时,使用 writeStream.write(chunk) 将数据片段写入可写流。
  3. 监听 ‘end’ 事件:当所有的数据片段都接收完毕后,调用 writeStream.end() 关闭写入流,确保所有数据都被正确写入文件。

这种方法能够保证数据按顺序写入文件,避免了并发写入导致的数据混乱问题。


不明白为什么fs.appendFile(filePath, body, "utf8", function (err) {这里要加个utf8

去掉就可以?

fs.appendFile(filename, data, encoding=‘utf8’, [callback])# Asynchronously append data to a file, creating the file if it not yet exists. data can be a string or a buffer. The encoding argument is ignored if data is a buffer.

Example:

fs.appendFile(‘message.txt’, ‘data to append’, function (err) { if (err) throw err; console.log(‘The “data to append” was appended to file!’); });

例如

 http.get(options, function(resp){
        console.log(resp.statusCode);
        if (resp.statusCode !== 200) {
            console.log('failed to get ' + file_url);
            return;
        }
        resp.pipe(fs.createWriteStream(path.join(baseDir, filename)));
        console.log(filename);
}).on('error', function(err) {
    console.log(err.message);
});

fs.appendFile 不能保证数据按调用顺序添加到文件里。测试代码(不知道为什么执行这段代码会报错……):

var fs = require('fs');
for (var i = 0; i < 10000; i++) {
  fs.appendFile('/tmp/appendTest', i % 10);
  if (i % 10 == 9) {
    fs.appendFile('/tmp/appendTest', '\n');
  }
}

cat /tmp/appendTest 结果中出现:

...
0123456789
0123456789
012345679
0123456789
01234567898
0123456789
0123456789
...

node 处处都是异步~~

WriteStream来写入文件,可以保证顺序

发现改成同步调用,也会出现图片花的情况。

果然用pipe可以解决图片花的问题,请问什么时候pipe完,因为我要等图片生成后通知客户端去取。是resp.on(‘end’, function () {这个事件吗?

使用 fs.appendFile 在处理大图片时可能会因为异步操作导致数据写入不完整或错位,从而产生“花图”的情况。这是因为 fs.appendFile 是异步的,多个数据块可能在短时间内并发写入文件,导致部分数据覆盖或错位。

你可以考虑使用 fs.createWriteStream 来创建一个可写流,并将微信接口返回的数据直接写入该流中。这样可以确保数据按照顺序完整地写入文件,避免并发写入问题。

示例代码如下:

const https = require('https');
const fs = require('fs');

const filePath = 'path/to/your/image.jpg';
const writeStream = fs.createWriteStream(filePath);

resHttps.on('data', function (body) {
  writeStream.write(body);
});

resHttps.on('end', function () {
  writeStream.end();
});

上述代码中,我们创建了一个可写流 writeStream,并在接收到数据时将数据写入该流。当所有数据接收完毕后,调用 writeStream.end() 方法结束写入。这样可以确保数据按顺序完整写入文件,避免图片花掉的问题。

回到顶部