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

使用Node.js上传至S3后无法获取对象公网链接(AWS SDK v3)

获取S3上传文件的URL(AWS SDK v3)

AWS SDK for JavaScript v3的PutObjectCommand响应确实没有v2里的Location字段,你可以通过以下两种方式获取文件URL:

1. 直接拼接公开访问URL(适用于公开可读的对象)

如果你的S3桶配置了对象公开可读(比如通过桶策略或ACL设置),可以直接用S3的固定URL格式拼接:

https://<bucket-name>.s3.<region>.amazonaws.com/<object-key>

修改你的上传函数,在上传时记录对象的Key,上传完成后拼接URL:

const { S3Client, PutObjectCommand } = require("@aws-sdk/client-s3");
const uuid = require("uuid").v1;

exports.s3Uploadv3 = async (files) => {
  const s3client = new S3Client({
    // 确保指定region,若未指定会从环境变量/默认配置读取
    region: process.env.AWS_REGION,
  });

  // 为每个文件生成params并保存Key
  const uploadTasks = files.map((file) => {
    const key = `uploads/${uuid()}-${file.originalname}`;
    const params = {
      Bucket: process.env.AWS_BUCKET_NAME,
      Key: key,
      Body: file.buffer,
    };
    // 同时保存params和key,方便后续生成URL
    return { params, key };
  });

  // 执行上传并获取结果
  const results = await Promise.all(
    uploadTasks.map(async ({ params, key }) => {
      const response = await s3client.send(new PutObjectCommand(params));
      // 拼接公开URL
      const url = `https://${process.env.AWS_BUCKET_NAME}.s3.${s3client.config.region}.amazonaws.com/${key}`;
      return {
        ...response,
        url, // 添加URL到返回结果
      };
    })
  );

  return results;
};

2. 生成预签名URL(适用于私有对象)

如果你的S3对象是私有访问的,需要生成带签名的预签名URL,客户端可以通过这个URL在有效期内访问文件。需要先安装@aws-sdk/s3-request-presigner:

npm install @aws-sdk/s3-request-presigner

然后修改函数:

const { S3Client, PutObjectCommand, GetObjectCommand } = require("@aws-sdk/client-s3");
const { getSignedUrl } = require("@aws-sdk/s3-request-presigner");
const uuid = require("uuid").v1;

exports.s3Uploadv3 = async (files) => {
  const s3client = new S3Client({
    region: process.env.AWS_REGION,
  });

  const uploadTasks = files.map((file) => {
    const key = `uploads/${uuid()}-${file.originalname}`;
    const params = {
      Bucket: process.env.AWS_BUCKET_NAME,
      Key: key,
      Body: file.buffer,
    };
    return { params, key };
  });

  const results = await Promise.all(
    uploadTasks.map(async ({ params, key }) => {
      const response = await s3client.send(new PutObjectCommand(params));
      // 生成预签名URL,设置有效期(比如3600秒=1小时)
      const signedUrl = await getSignedUrl(
        s3client,
        new GetObjectCommand({
          Bucket: process.env.AWS_BUCKET_NAME,
          Key: key,
        }),
        { expiresIn: 3600 }
      );
      return {
        ...response,
        url: signedUrl, // 返回预签名URL
      };
    })
  );

  return results;
};

注意事项

  • 确保S3Client的region配置正确,否则拼接的URL会无效。
  • 若使用公开URL,需确保桶的对象有公开读权限(可通过桶策略或在PutObject参数中设置ACL: 'public-read')。
  • 预签名URL的有效期可以根据需求调整,最长不超过7天(受AWS限制)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 01:28:26