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

如何修改Javascript代码安全上传Blob至AWS S3避免文件损坏

解决Blob上传S3后文件损坏的问题

你的核心问题是二进制音频数据在传输过程中被错误编码,导致S3存储的文件无法正常播放。下面给你几个可行的JS修改方案,配合Lambda的调整就能彻底解决这个问题:

方案1:用FormData封装Blob(推荐,贴合标准文件上传流程)

直接传递Blob时,jQuery对二进制数据的处理容易出现编码偏差,用FormData可以确保数据以正确的multipart格式传输:

修改JS中ondataavailable里的AJAX逻辑:

// 提前声明变量,避免全局污染
var audioChunks = [];
var rec;

navigator.mediaDevices.getUserMedia({audio:true})
.then(stream => {
  // 可以指定录制格式,比如webm(Chrome默认)或mp4(Safari支持)
  rec = new MediaRecorder(stream, { mimeType: 'audio/webm' });
  rec.ondataavailable = e => {
    audioChunks.push(e.data);
    if (rec.state == "inactive"){
      const blob = new Blob(audioChunks, { type: 'audio/webm' });
      const formData = new FormData();
      // 第三个参数是文件名,格式要和Blob的type一致
      formData.append('audio-file', blob, 'recording.webm');

      $.ajax({
        type: "POST",
        url: 'https://aws-api-url/prod/audio',
        data: formData,
        crossDomain: true,
        processData: false, // 阻止jQuery自动处理FormData
        contentType: false, // 让浏览器自动生成multipart的Content-Type
        headers: {"x-api-key": 'someKey'},
        success: () => console.log('音频上传成功'),
        error: (err) => console.error('上传失败:', err)
      });
    }
  }
})
.catch(e=>console.log(e));

对应的Lambda需要解析multipart数据(可以用aws-lambda-multipart-parser第三方库):

import json
import boto3
from lambda_multipart_parser import parser

def lambda_handler(event, context):
    # 强烈建议用IAM角色授权S3权限,不要硬编码密钥!
    s3_client = boto3.client('s3')
    parsed_data = parser.parse(event)
    audio_file = parsed_data['audio-file']
    
    # 上传时指定正确的Content-Type,确保下载后能正常播放
    s3_client.put_object(
        Body=audio_file.content,
        Bucket='bucket',
        Key='incoming/recording.webm',
        ContentType=audio_file.content_type
    )
    
    return {
        'statusCode': 200,
        'headers': { 'Access-Control-Allow-Origin': '*' },
        'body': json.dumps('音频上传成功')
    }

方案2:将Blob转为Base64字符串传输(更简单,无需处理multipart)

把二进制数据转成Base64字符串,以JSON格式传输,Lambda解码后再保存原始二进制:

修改JS代码:

var audioChunks = [];
var rec;

navigator.mediaDevices.getUserMedia({audio:true})
.then(stream => {
  rec = new MediaRecorder(stream, { mimeType: 'audio/webm' });
  rec.ondataavailable = e => {
    audioChunks.push(e.data);
    if (rec.state == "inactive"){
      const blob = new Blob(audioChunks, { type: 'audio/webm' });
      const reader = new FileReader();
      
      reader.onload = function(event) {
        // 去掉Base64前缀(data:audio/webm;base64,),只保留编码内容
        const base64Audio = event.target.result.split(',')[1];
        
        $.ajax({
          type: "POST",
          url: 'https://aws-api-url/prod/audio',
          data: JSON.stringify({ audio: base64Audio }),
          crossDomain: true,
          processData: false,
          headers: {"x-api-key": 'someKey'},
          contentType: 'application/json', // 明确告知后端是JSON格式
          success: () => console.log('音频上传成功'),
          error: (err) => console.error('上传失败:', err)
        });
      };
      
      reader.readAsDataURL(blob);
    }
  }
})
.catch(e=>console.log(e));

对应的Lambda修改:

import json
import boto3
import base64

def lambda_handler(event, context):
    s3_client = boto3.client('s3')
    request_body = json.loads(event['body'])
    # 解码Base64字符串为原始二进制数据
    audio_binary = base64.b64decode(request_body['audio'])
    
    s3_client.put_object(
        Body=audio_binary,
        Bucket='bucket',
        Key='incoming/recording.webm',
        ContentType='audio/webm'
    )
    
    return {
        'statusCode': 200,
        'headers': { 'Access-Control-Allow-Origin': '*' },
        'body': json.dumps('音频上传成功')
    }

额外重要提醒

  • 禁止硬编码AWS密钥:给Lambda配置具备S3上传权限的IAM角色,删除代码中硬编码的aws_access_key_id和aws_secret_access_key,这是严重的安全漏洞。
  • 匹配音频格式:不同浏览器的MediaRecorder默认格式不同(Chrome为webm,Safari为mp4),创建Blob时要指定正确的type,同时S3上传时设置对应的ContentType,否则下载后的文件可能无法播放。
  • 变量提前声明:在JS开头显式声明audioChunks和rec变量,避免全局变量污染引发的潜在问题。

内容的提问来源于stack exchange,提问作者Jaskaran Singh Puri

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:36:54