如何通过设置正确的偏移量和位置来读取文件并使用手动缓冲写入 Nodejs 中的响应?

Kis*_*ada 7 file-io node.js

我想以 64 字节的间隔读取一个文件。而且我也不想使用任何内部实现缓冲的功能。我想手动进行缓冲。所以我开始使用 fs.read()。我很努力,但我真的不知道如何设置位置,告诉从文件中读取的位置和缓冲区中的偏移量以开始写入。
所以我找到了很少的资源并开始自己实现。但我所做的似乎完全错误。请在下面找到我的代码。

app.get('/manualBufferAnother', function (req, res, next) {
   var filePath = path.join(__dirname, 'Koala.jpg');
   console.log("FilePath is: "+filePath);
   var fileName = path.basename(filePath);
   var mimeType = mime.lookup(filePath);
   var stat = fs.statSync(filePath);

   res.writeHead(200, {
         "Content-Type": mimeType,
         "Content-Disposition" : "attachment; filename=" + fileName,
         'connection': 'keep-alive',
         "Content-Length": stat.size,
         "Transfer-Encoding": "chunked"
   });

   fs.open(filePath, 'r', function(err, fd) {
       var completeBufferSize = stat.size;
       var offset = 0;  //is the offset in the buffer to start writing at
       var length = 511; //is an integer specifying the number of bytes to read
       var position = 0;  //is an integer specifying where to begin reading 
       from in the file. If position is null, data will be read from the current file position
       var buffer = new Buffer(completeBufferSize);
       buf(res,fd,offset,position,length,buffer,stat);        
   });
 });

var buf = function(res,fd,offset,position,length,buffer,stat) {
if(position+buffer.length < length) {
    fs.read(fd,buffer,offset,length,position,function(error,bytesRead,bufferr {
        res.write(bufferr.slice(0,bytesRead));
        console.log("Bytes Read: "+bytesRead);
        position=position+bufferr.length;
        buf(res,fd,offset,position,length,bufferr,stat);
    })
} else {
    fs.read(fd,buffer,offset,length,position,function(error,bytesRead,bufferr) {
        console.log("Bytes Read in else: "+bytesRead);
        res.end(bufferr.slice(0,bytesRead));
        fs.close(fd)
    })
}
}
Run Code Online (Sandbox Code Playgroud)

我知道这段代码做了很多错误的事情。但我不知道正确的方法。我应该使用任何循环来设置和存储位置和偏移值吗?如果你给我提供很好的参考,真的会有帮助吗?

Jam*_*son 6

下面是一个例子:

res.writeHead(...);
var SIZE = 64; // 64 byte intervals
fs.open(filepath, 'r', function(err, fd) {
  fs.fstat(fd, function(err, stats) {
    var bufferSize = stats.size;
    var buffer = new Buffer(bufferSize),
    var bytesRead = 0;

    while (bytesRead < bufferSize) {
      var size = Math.min(SIZE, bufferSize - bytesRead);
      var read = fs.readSync(fd, buffer, bytesRead, size, bytesRead);
      bytesRead += read;
    }
    res.write(buffer);
  });
});
Run Code Online (Sandbox Code Playgroud)

我应该使用任何循环来设置和存储位置和偏移值吗?

是的,你可以,但要小心。在 Node.js 中,大多数文件系统功能都是异步的(非阻塞)。您可能已经意识到,将异步函数放入循环中会导致问题。您可以通过查看 Node.js 文档并检查是否有callback参数来判断函数是否异步 。所以read在循环内使用是不好的。我们可以改为使用readSync. 这是同步的(阻塞),类似于 C 的read()函数(也是阻塞的)。

我真的不知道如何设置 position 来告诉文件中读取的位置和缓冲区中的偏移量以.

readSync函数的参数控制从文件中读取的位置以及要写入的目标缓冲区中的位置。

//                        /----- where to start writing at in `buffer`    
fs.readSync(fd, buffer, offset, length, position)
//                                           \------- where to read from in the 
//                                                    file given by `fd`
Run Code Online (Sandbox Code Playgroud)

注意:上面的样式是 C 的惯用方式,但在 Javascript 中它被认为是不好的做法——代码不能很好地扩展。通常,您永远不想使用同步函数,因为它们会阻塞 Javascript 使用的单线程执行(也称为“阻塞事件循环”)。
Express.js

同步函数和方法会在它们返回之前阻塞正在执行的进程。对同步函数的单个调用可能会在几微秒或几毫秒内返回,但是在高流量网站中,这些调用会累加并降低应用程序的性能。避免在生产中使用它们。尽管 Node 和许多模块提供了它们功能的同步和异步版本,但在生产中始终使用异步版本

如果您想要最惯用和高性能的代码,使用.pipe()and Streams(异步风格)通常是要走的路。很抱歉这样说:没有官方来源/流行网站会描述通过 C 风格的阻塞和缓冲使用同步函数的文件操作,因为它在 Node.js 中是不好的做法。