PUT请求上传至AWS S3后,如何获取图片访问URL?
问题
我正在处理向s3.amazonaws.com上传图片的需求,已编写两个回调函数:
- 从后端获取用于上传的预签名URL;
- 使用该预签名URL通过PUT请求将图片上传至S3。
但上传完成后,PUT请求返回空响应,无法获取已上传图片的访问URL。相关代码如下:
// callback for getting upload url from my backend - works OK const getPresignedUrl = useCallback( async (imageName: string) => { const configurationObject = { method: 'get', url: getUploadUrl(imageName, uploadImageCategory.AVATARS), headers: { Authorization: `Bearer ${token}`, }, }; const {data} = await axios(configurationObject); return data; }, [getUploadUrl, token], ); // function to get image body from uri - also OK const getBlob = async (fileUri: string) => { const resp = await fetch(fileUri); const imageBody = await resp.blob(); return imageBody; }; // callback that puts my image to s3 server - seems like it's OK const uploadUsingPresignedUrl = useCallback( async (preSignedUrl: string) => { const imageBody = await getBlob(uri); const configurationObject = { method: 'PUT', url: preSignedUrl, data: { body: imageBody, }, }; const {data} = await axios(configurationObject); return data; }, [uri], );
后续调用代码:
const onUploadImage = useCallback(async () => { const imageName = getImageName(uri); //just util for getting right image name const presignedUrl = await getPresignedUrl(imageName); console.log('presignedUrl', presignedUrl); // I see generated URL in response const putImageOnAws = await uploadUsingPresignedUrl(presignedUrl); console.log('putImageOnAws', putImageOnAws); // Response is empty }, [getImageName, getPresignedUrl, uploadUsingPresignedUrl, uri]); useEffect(() => { if (uri) { setAvatar(uri); onUploadImage() .then() .catch(err => console.log('err: ', err)); } }, [onUploadImage, uri]);
请问如何获取已上传至S3的图片访问URL?
解决方案
核心逻辑说明
S3的PUT预签名URL请求本身不会返回图片访问URL——预签名URL仅用于授权上传操作,和最终的公开访问地址是两个独立的概念,除非你配置了S3静态网站托管且两者路径完全一致,否则无法直接从PUT响应中拿到访问地址。
具体实现方法
方法一:后端同步返回访问URL
在后端生成预签名URL的接口中,直接拼接好该文件对应的S3公开访问地址,和预签名URL一起返回给前端。后端提前知晓S3桶的域名、文件存储路径,拼接逻辑简单可靠,还能统一控制权限。方法二:前端自行拼接访问URL
如果你已知S3桶的公开访问域名(例如https://your-bucket-name.s3.amazonaws.com/),以及上传时使用的imageName,可以直接拼接成访问地址:https://your-bucket-name.s3.amazonaws.com/${imageName}。
注意:此方法要求该S3对象的权限为公开可读,否则拼接后的地址无法直接访问。修复上传代码的潜在问题
你的uploadUsingPresignedUrl函数存在参数传递错误,axios的PUT请求中data字段需要直接传入Blob对象,而非嵌套在body属性中,同时建议指定正确的Content-Type:const uploadUsingPresignedUrl = useCallback( async (preSignedUrl: string) => { const imageBody = await getBlob(uri); const configurationObject = { method: 'PUT', url: preSignedUrl, data: imageBody, // 直接传入Blob对象 headers: { 'Content-Type': 'image/jpeg' // 根据实际图片类型调整,比如image/png } }; // PUT请求成功无需返回data,只需确认请求完成即可 await axios(configurationObject); }, [uri], );
内容的提问来源于stack exchange,提问作者John Red
相关产品推荐
相关产品推荐

