zl程序教程

您现在的位置是:首页 >  Javascript

当前栏目

返回给前端图片流

2023-03-20 15:00:25 时间

在开发时遇到造一个这样的问题,场景是这样的,前端需要一个接口,根据用户的id返回用户的图片流,当时没明白什么是流,后来通过查看nodejs的文档,nodejs具有流场景的应用,代码如下:

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在返回给前端的时候,一班需要设置文件类型响应头,常用文件类型通用头部有:

{
  "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"
}

我们可以在返回文件前先设置响应头:

//设置请求的返回头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();

如果动态文件流处理:

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();
    });
}

这里处理相较于第一段代码,是后端全部处理完后,在一次性返回给前端,个人感觉没有优劣之分,感觉前一种效率更高。

以上便是返回给前端图片流的详细内容,希望对你有所帮助。