使用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
相关产品推荐
相关产品推荐

