在开发时遇到造一个这样的问题,场景是这样的,前端需要一个接口,根据用户的id返回用户的图片流,当时没明白什么是流,后来通过查看nodejs的文档,nodejs具有流场景的应用,代码如下:
代码语言:javascript复制const express = require('express');
const router = express.Router();
const fs = require('fs')
const path = require('path')
router.get('/', (req, res, next) => {
const qrcodeName = Date.now() '-' Math.random().toString(36).slice(-6);
const filePath = path.resolve(__dirname, `./../public/qrcode/${qrcodeName}.png`);
// 给客户端返回一个文件流
//格式必须为 binary,否则会出错
// 创建文件可读流
const cs = fs.createReadStream(filePath);
cs.on("data", chunk => {
res.write(chunk);
})
cs.on("end", () => {
res.status(200);
res.end();
})
})
module.exports = router;
原理:我们创建一个可读的流,然后开始读的时候,就对接口响应流,针对大文件也不会有问题,毕竟是流,读出一部分,然后就响应,一开始使用readFile, 但是发现,send后竟然是文件下载,后面想想也是,readFile 读出的是二进制的文件,浏览器他不明白你的二进制的文件要怎么处理,就给直接下载了,流的好处是后端程序压力小。
补充一下:http在返回给前端的时候,一班需要设置文件类型响应头,常用文件类型通用头部有:
代码语言:javascript复制{
"css": "text/css",
"gif": "image/gif",
"html": "text/html",
"ico": "image/x-icon",
"jpeg": "image/jpeg",
"jpg": "image/jpeg",
"js": "text/javascript",
"json": "application/json",
"pdf": "application/pdf",
"png": "image/png",
"svg": "image/svg xml",
"swf": "application/x-shockwave-flash",
"tiff": "image/tiff",
"txt": "text/plain",
"wav": "audio/x-wav",
"wma": "audio/x-ms-wma",
"wmv": "video/x-ms-wmv",
"xml": "text/xml"
}
我们可以在返回文件前先设置响应头:
代码语言:javascript复制//设置请求的返回头type,content的type类型列表见上面
response.setHeader("Content-Type", contentType);
//格式必须为 binary 否则会出错
var content = fs.readFileSync(url,"binary");
response.writeHead(200, "Ok");
response.write(content,"binary"); //格式必须为 binary,否则会出错
response.end();
如果动态文件流处理:
代码语言:javascript复制response.set( 'content-type', mimeType );//设置返回类型
var stream = fs.createReadStream( imageFilePath );
var responseData = [];//存储文件流
if (stream) {//判断状态
stream.on( 'data', function( chunk ) {
responseData.push( chunk );
});
stream.on( 'end', function() {
var finalData = Buffer.concat( responseData );
response.write( finalData );
response.end();
});
}
这里处理相较于第一段代码,是后端全部处理完后,在一次性返回给前端,个人感觉没有优劣之分,感觉前一种效率更高。
以上便是返回给前端图片流的详细内容,希望对你有所帮助。