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

AWS SDK生成S3对象读取预签名URL错误问题排查

解决AWS S3预签名URL因Key二次转义导致的NoSuchKey错误

问题背景

我使用AWS S3存储视频,通过预签名URL限制访问权限,但调用getVideoReadSignedUrl生成的URL访问时提示NoSuchKey错误:

  • 数据库中存储的是多部分上传后completeMultiPartUpload返回的Location,其中/被转义为%2F,示例URL:https://BUCKET_NAME.s3.REGION.amazonaws.com/videos%2F60e589xxxxxxxxx463c.mp4
  • S3实际存储的对象Key为videos/xxxxxxxxxxxxxxxxx.mp4,控制台获取的URL也使用原始/分隔
  • 解析数据库URL时得到的Key是videos%2Fxxxxxxxxxxxxxxxxx.mp4,传给getSignedUrl后会被二次转义为videos%252Fxxxxxxxxxxxxxxxxx.mp4,导致S3无法找到对应对象

解决方案

核心是在解析Key时解码URL编码的字符,将转义后的%2F还原为原始的/,确保传给S3的Key与实际存储的一致。

修正解析Key的函数

修改parseVideoKeyFromVideoUrl,添加decodeURIComponent解码步骤:

const parseVideoKeyFromVideoUrl = (object_url) => {
  const string_to_remove =
    "https://" + AWS_BUCKET_NAME + ".s3." + REGION + ".amazonaws.com/";
  const encoded_object_key = object_url.replace(string_to_remove, "");
  // 解码URL编码字符,还原%2F为/
  const object_key = decodeURIComponent(encoded_object_key);
  return object_key;
};

优化预签名URL生成函数(可选)

原函数用Promise封装回调,可改用AWS SDK提供的getSignedUrlPromise简化异步逻辑:

var getVideoReadSignedUrl = async function (url) {
  const key = awsS3Helpers.parseVideoKeyFromVideoUrl(url);
  try {
    const signedUrl = await s3.getSignedUrlPromise("getObject", {
      Bucket: AWS_BUCKET_NAME,
      Key: key,
      Expires: 300,
    });
    console.log("生成的预签名URL:", signedUrl);
    return signedUrl;
  } catch (err) {
    console.error("生成预签名URL失败:", err);
    throw err;
  }
};

效果说明

经过上述修改后,无论是数据库中存储的转义URL还是原始格式URL,都能解析出与S3实际存储一致的Key,生成的预签名URL不会出现二次转义问题,浏览器可正常访问视频资源。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 07:20:29