You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从服务器流式传输的二维码无法显示问题求助

NestJS生成二维码前端无法显示的修复方案

问题描述

后端使用qrcode库生成二维码,已验证本地保存PNG文件正常,但通过流返回给前端React后,图片仅显示占位符。Chrome中查看img的blob URL,复制打开可见PNG开头数据,但无法正常渲染。

问题根源

  1. 前端axios参数错误:responseType: 'blob'被错误放在请求体参数位置,而非axios的配置参数中,导致响应未被正确解析为Blob类型。
  2. 后端响应头缺失:未明确设置Content-Type: image/png,浏览器无法正确识别图片格式。
  3. 可选:Blob URL未清理:组件卸载时未释放Blob URL,存在内存泄漏风险。

修复步骤

1. 后端代码调整

服务层方法优化

移除本地保存代码(若无需持久化),并明确指定二维码类型:

async pipeQrCodeStream(stream: any, otpauthUrl: string) {
  // 若不需要本地保存,可删除以下两行
  // const filePath = '/qrcode.png'
  // await qrcode.toFile(filePath, otpauthUrl);
  
  // 明确指定生成PNG格式的二维码
  await qrcode.toFileStream(stream, otpauthUrl, { type: 'png' });
}

控制器层设置响应头

确保控制器传递响应对象并设置正确的Content-Type:

import { Controller, Post, Res } from '@nestjs/common';
import { Response } from 'express';

@Controller()
export class QrCodeController {
  constructor(private readonly qrCodeService: QrCodeService) {}

  @Post('/myqrcode')
  async getQrCode(@Res() res: Response) {
    const otpauthUrl = 'your-actual-otpauth-url'; // 替换为实际的OTP授权URL
    await this.qrCodeService.pipeQrCodeStream(res, otpauthUrl);
    // 设置响应头,告知浏览器返回的是PNG图片
    res.setHeader('Content-Type', 'image/png');
  }
}

2. 前端React代码修复

修正axios请求参数位置,添加Blob URL清理逻辑:

import { useState, useEffect } from 'react';
import axios from 'axios';
import { Container } from '@mui/material'; // 假设使用MUI的Container

const MyQrPage = () => {
    const [qrCodeUrl, setQrCodeUrl] = useState<string | null>(null);

    useEffect(() => {
        const fetchQrCode = async () => {
            try {
                // 修正axios参数:responseType放在第三个config参数中
                const response = await axios.post(
                    '/myqrcode',
                    {}, // 无请求体时传空对象
                    { responseType: 'blob' }
                );
                // 直接使用response.data(已正确解析为Blob)创建URL
                const url = URL.createObjectURL(response.data);
                setQrCodeUrl(url);
            } catch (error) {
                console.error('获取二维码失败:', error);
            }
        };

        fetchQrCode();
    }, []);

    // 组件卸载时释放Blob URL,避免内存泄漏
    useEffect(() => {
        return () => {
            if (qrCodeUrl) {
                URL.revokeObjectURL(qrCodeUrl);
            }
        };
    }, [qrCodeUrl]);

  return (
    <Container maxWidth="sm">
      {qrCodeUrl ? (
        <div>
            <img src={qrCodeUrl} alt="QR Code" style={{ maxWidth: '100%' }} />
        </div>
      ) : (
        <div>二维码加载中...</div>
      )}
    </Container>
  );
};

export default MyQrPage;

验证方法

  1. 重启NestJS后端服务。
  2. 刷新前端页面,查看二维码是否正常显示。
  3. 检查Network请求的响应头,确认Content-Type为image/png,响应数据为二进制PNG格式。

内容的提问来源于stack exchange,提问作者jelly5798

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 01:15:57