如何从 NAPI节点插件接口读取文件并使用 nodejs 文件流写入不同的文件

问题描述

我正在尝试读取 NAPI 应用程序中的文件调用回调函数将其写入 nodejs 应用程序中的 writestream。

exmaple_Class.cpp

void readFromTransientFile(const Napi::CallbackInfo &info) 
{
    Napi::Env env = info.Env();
    Napi::HandleScope scope(env);

    Napi::Function cb = info[0].As<Napi::Function>();
    

    while ((this->actualClass_->pos() < this->actualClass_->size()) &&
               ((readLength = this->actualClass_->read((void *)tempBuffer,sizeof(tempBuffer))) > 0))
        {

            //cb.Call(env.Global(),{Napi::Buffer<char>::New(env,tempBuffer,sizeof(tempBuffer))});
            cb.Call(env.Global(),{Napi::String::New(env,tempBuffer)});

            writetotal += readLength;
        }
    std::cout << "Done!" << std::endl;
}

exmaple_Class.js

const testAddon = require("./build/Release/testaddon.node");
const fs = require("fs");

const prevInstance = new testAddon.OtClass();
const writeStream = fs.createWriteStream("./downloads/lake.jpg");

  prevInstance.readFromTransientFile(
    function (msg) {
      console.log(">> received buffer from getFile: ",msg);
      console.log(">> typeof msg",typeof msg);
      writeStream.write(msg);
    }
  );

writeStream.end();

C++ 端函数的局限是不能返回值,所以数据必须在回调中返回。有趣的是,如果它是一个文本文件,它可以正常工作,但对于其他类型的文件,如 zip 或 jpeg,我得到的数据是乱码。如果我将文件描述符传递给 C++ 函数并使用 UNIX 写入函数,那么我会得到该文件。但我也想使用 express 通过 HTTP 发送该数据。那么出了什么问题呢?如何在 NAPI 对象中正确包装和返回二进制数据。

解决方法

为了后代。数据编码是错误。二进制数据表示为Byte Array,然后转换成Buffer供writeStreamer消费。

fileReader.cpp

void functionexample::ReadRawFile(const Napi::CallbackInfo &info)
{
    Napi::Env env = info.Env();
    Napi::HandleScope scope(env);

    // nodejs callback
    Napi::Function cb = info[0].As<Napi::Function>();

    char *file_name = "lake.jpg";
    int i = 0;
    const int BLOCK_SIZE = 1024;
    char buffer[BLOCK_SIZE];
    ifstream ifs;

    ifs.open(file_name,ifstream::binary | ifstream::in);

    while (1)
    {
        memset(buffer,BLOCK_SIZE);

        ifs.read(buffer,BLOCK_SIZE);

        cout << i << " | buffer size: " << ifs.gcount() << endl;
        i++;

        ///  PASSING DATA TO THE NODEJS APPLICATION
        ///  AS A BINARY ARRAY PPINTER POINTING TO THE buffer
        cb.Call(env.Global(),{Napi::ArrayBuffer::New(env,buffer,ifs.gcount())});

        ofs.write(buffer,ifs.gcount());
        if (!ifs)
            break;
    }

    ifs.close();
}

fileWriter.js

const fs = require("fs");
const testAddon = require("./build/Release/testaddon.node");

// Create a write streamer 
const wstream = fs.createWriteStream("./lake-copied-nodejs.jpg");

testAddon.readFile(function(msg) {
  // handle data encoding
  const buf = Buffer.alloc(msg.byteLength);
  const view = new Uint8Array(msg);
  for (var i = 0; i < buf.length; ++i) {
    buf[i] = view[i];
  }

  // write binary data to file
  wstream.write(buf);
});
wstream.close();

module.exports = testAddon;