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

如何流式上传MP3至S3并立即获取可访问的资源URL?

如何将流写入S3并立即获取读取内容的链接?

问题本质

S3的对象是原子性创建的——不管是普通上传还是分段上传,只有当整个文件上传完成(分段上传还需执行合并操作),对象才会正式存在并可被访问。你当前的代码用s3.upload默认采用分段上传,上传过程中目标对象并未创建,所以提前生成的预签名URL会返回404,必须等上传完成才能正常访问。

解决方案

要实现“边上传边让用户流式读取”的需求,不能直接通过S3对象完成,需要调整架构:

方案1:同时向用户和S3推送流

在Node.js中,创建一个HTTP端点,将音频流同时转发给用户(实时收听)和S3(后台归档)。这样用户无需等待S3上传完成,就能立即开始接收内容。

示例代码:

const express = require('express');
const stream = require('stream');
const { S3Client, Upload } = require('@aws-sdk/lib-storage');

const app = express();
const s3Client = new S3Client({ region: '你的区域' });

app.get('/stream-audio', (req, res) => {
  // 设置音频流式响应头
  res.setHeader('Content-Type', 'audio/mpeg');
  res.setHeader('Transfer-Encoding', 'chunked');

  // 创建分流管道,同时对接用户响应和S3上传
  const passThrough = new stream.PassThrough();

  // 后台上传到S3
  const uploadParams = {
    Bucket: '你的存储桶名',
    Key: '音频文件路径.mp3',
    Body: passThrough
  };
  const upload = new Upload({
    client: s3Client,
    params: uploadParams
  });
  upload.on('completed', (data) => {
    console.log('S3上传完成,可访问URL:', data.Location);
    // 这里可以将S3 URL发送给用户(比如通过WebSocket)
  });
  upload.on('error', (err) => console.error('S3上传失败:', err));
  upload.done();

  // 将原始音频流同时推送给用户和S3
  myAudioStream.pipe(passThrough).pipe(res);
});

app.listen(3000, () => console.log('服务启动在3000端口'));

方案2:使用AWS媒体服务(适合专业流式场景)

如果是生产环境的媒体流式需求,可以用AWS MediaPackage或MediaLive搭建实时流式服务,同时将内容归档到S3。用户通过MediaPackage的端点实时收听,后台自动完成S3存储。

方案3:优化S3上传速度(无法边传边读,但缩短等待时间)

如果必须等上传完成再提供S3 URL,可以通过分段并行上传减少总耗时:

  • 使用AWS SDK的Upload类(@aws-sdk/lib-storage),它会自动拆分文件为分片并行上传,比传统s3.upload更快。
  • 启用S3传输加速(Transfer Acceleration),利用CloudFront边缘节点提升上传速度。

原代码问题说明

你代码中的s3.upload采用分段上传机制,只有当所有分片上传完成并调用合并接口后,S3才会创建目标对象。提前生成的预签名URL指向的是尚未存在的对象,因此返回404错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 14:45:55