React前端通过预签名URL直传AWS S3后如何获取对象key?
S3预签名URL上传后获取对象Key的实现方案
核心实现思路
你可以通过以下两种方案获取上传对象的Key,优先推荐第一种:
- 方案1(推荐):服务端生成预签名URL时同步返回S3对象Key
S3预签名URL是服务端基于指定的对象Key、权限、过期时间生成的,生成时直接将该Key和uploadUrl一起放在接口响应中返回给前端,前端上传成功后直接将这个Key传给你的服务端存储即可,无需额外解析,可靠性最高。 - 方案2(前端解析预签名URL获取Key):如果暂时无法修改服务端接口,可以从预签名URL中提取Key
S3预签名URL的标准格式为https://<桶名>.s3.<区域>.amazonaws.com/<对象Key>?<签名参数>,提取域名后、问号前的部分,做URL解码即可得到Key。
代码优化及完整实现
你现有上传代码存在配置错误:使用PUT方法上传到S3预签名URL时,不需要使用FormData,也不要设置multipart/form-data的Content-Type,否则会导致上传的文件格式异常。优化后的完整代码如下:
const handleSubmit = async (e) => { e.preventDefault() // 1. 从服务端获取预签名URL和对应Key(如果用方案1,服务端直接返回key字段) const res = await fetch("/api/website/aws/get-s3-upload-url") const data_2 = await res.json() const profile_url = data_2.uploadUrl // 方案1直接取返回的key:const s3Key = data_2.key // 方案2解析URL获取key: const urlObj = new URL(profile_url) const s3Key = decodeURIComponent(urlObj.pathname.slice(1)) // 去掉pathname开头的斜杠后解码得到key console.log(`S3对象Key为:${s3Key}`) // 2. 上传图片到S3 const resp = await fetch(profile_url, { method: "PUT", headers: { "Content-Type": profile.type, // 直接使用文件本身的MIME类型 }, body: profile, // 直接传文件对象,不需要封装FormData }) // 3. 确认上传成功后,将key传给你的服务端存储 if (resp.ok) { await fetch("/api/website/save-user-avatar-key", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ avatar_key: s3Key }) }) alert("头像上传成功") } else { alert("头像上传失败,请重试") } }
内容的提问来源于stack exchange,提问作者Rich MindSet Rohit
相关产品推荐
相关产品推荐

