面试题答案
一键面试利用流优化大文件传输性能
在Node.js使用HTTP模块处理大文件传输时,流(Stream)通过以下方式优化性能:
- 避免内存占用:流不会一次性将整个文件读入内存,而是逐块处理数据,这在处理大文件时极大地减少了内存占用。
- 提高传输效率:数据可以在产生和消费的同时进行传输,而不需要等待整个文件被完全读取或生成,从而提高了传输效率。
流的不同类型及协作方式
- 可读流(Readable Stream):用于从源(如文件系统中的文件)读取数据。在大文件传输中,它从文件逐块读取数据。
- 可写流(Writable Stream):用于将数据写入目标(如HTTP响应或者另一个文件)。在大文件传输中,它将可读流读取的数据逐块写入到目标位置。
- 管道(pipe):通过
pipe
方法,可以将可读流和可写流连接起来,实现数据的自动流动。可读流一旦有数据可读,就会自动将数据推送到可写流,这简化了数据传输的过程并且高效地管理了背压(backpressure)。
代码示例 - 文件下载
const http = require('http');
const fs = require('fs');
const server = http.createServer((req, res) => {
const filePath = 'largeFile.txt'; // 假设要下载的大文件
const readStream = fs.createReadStream(filePath);
// 设置响应头
res.setHeader('Content-Disposition', 'attachment; filename="largeFile.txt"');
res.setHeader('Content-Type', 'text/plain');
// 使用管道将可读流连接到可写流(HTTP响应)
readStream.pipe(res);
// 处理错误
readStream.on('error', (err) => {
res.statusCode = 500;
res.end('Error occurred while reading the file');
});
});
const port = 3000;
server.listen(port, () => {
console.log(`Server running on port ${port}`);
});
代码示例 - 文件上传
const http = require('http');
const fs = require('fs');
const server = http.createServer((req, res) => {
if (req.method === 'POST') {
const writeStream = fs.createWriteStream('uploadedFile.txt');
// 将HTTP请求(可读流)的数据管道到文件写入流(可写流)
req.pipe(writeStream);
writeStream.on('finish', () => {
res.end('File uploaded successfully');
});
// 处理错误
req.on('error', (err) => {
res.statusCode = 500;
res.end('Error occurred while uploading the file');
});
writeStream.on('error', (err) => {
res.statusCode = 500;
res.end('Error occurred while writing the file');
});
} else {
res.end('Only POST method is allowed for file upload');
}
});
const port = 3000;
server.listen(port, () => {
console.log(`Server running on port ${port}`);
});