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

React流式音频缓存异常:播放旧文件而非更新后文件

音频内容更新后,PlaySound组件仍播放旧文件的解决办法

问题

后端已实现音频文件内容更新(路径和文件名保持不变),但React的<PlaySound />组件始终播放旧音频内容,而非更新后的版本。

已尝试的无效方案

  • 将row.text作为组件key强制触发组件更新
  • 在请求URL后添加随机GUID作为seed参数
  • 后端设置no-cache等缓存控制响应头

相关代码片段

组件调用代码

<PlaySound key={ row.text } path={ row.location.path } filename={ row.location.filename } />

PlaySound组件代码

import React, { Component } from 'react';
import { genUID } from '../../../helpers/helperFunctions';

class PlaySound extends Component
{
    playSound(path, filename) {
        var endpoint = "http://0.0.0.0:8001/api/stream"
        var url = endpoint + "?path=" + path + "&filename=" + filename + "&seed=" + genUID()
        var audio = new Audio(url);
        console.log(audio);
        audio.load();
        audio.play();        
    }

    render() 
    {
        return (
            <div>
                <span onClick={() => this.playSound(this.props.path, this.props.filename)}>&#9658;</span>
            </div>
        );
    }
}

export default PlaySound

Node.js/Express后端流式音频实现

app.get(API_VERSION + '/stream', (req, res) =>
{
  const filepath = req.query.path;
  const filename = req.query.filename;

  const file = '/app/audioExport/' + filepath + filename;

  try
  {
    res.writeHead(200, {
      'Cache-Control': 'no-cache, no-store, must-revalidate',
      'Pragma': 'no-cache',
      'Content-Type': 'audio/wav',
    });
    const rstream = fs.createReadStream(file);
    rstream.pipe(res);
  } catch (error) {
    res.json({error: error})
  }
});

可行解决方案

1. 通过Fetch获取Blob资源,绕过浏览器缓存

修改PlaySound组件的playSound方法,使用fetch直接获取音频Blob并创建临时URL,彻底避免浏览器缓存旧资源:

playSound(path, filename) {
  const endpoint = "http://0.0.0.0:8001/api/stream";
  const url = `${endpoint}?path=${path}&filename=${filename}&seed=${genUID()}`;
  
  fetch(url, { cache: 'no-store' })
    .then(response => {
      if (!response.ok) throw new Error('请求失败');
      return response.blob();
    })
    .then(blob => {
      const audioUrl = URL.createObjectURL(blob);
      const audio = new Audio(audioUrl);
      
      audio.play().catch(err => console.error('播放失败:', err));
      
      // 播放结束后释放临时URL,避免内存泄漏
      audio.onended = () => {
        URL.revokeObjectURL(audioUrl);
      };
    })
    .catch(err => console.error('获取音频失败:', err));
}

2. 强化后端缓存控制头

在后端响应中补充更严格的缓存禁止配置,确保浏览器不会缓存资源:

res.writeHead(200, {
  'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
  'Pragma': 'no-cache',
  'Expires': '0',
  'Content-Type': 'audio/wav',
});

3. 确保组件Key能准确触发更新

如果row.text不会随音频内容更新,改用音频文件的最后修改时间作为组件key:

  • 后端新增接口获取文件的mtime(修改时间),传给前端
  • 组件调用时使用该时间作为key:
    <PlaySound key={ row.fileMtime } path={ row.location.path } filename={ row.location.filename } />
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 05:17:42