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

PUT请求上传至AWS S3后,如何获取图片访问URL?

问题

我正在处理向s3.amazonaws.com上传图片的需求,已编写两个回调函数:

  1. 从后端获取用于上传的预签名URL;
  2. 使用该预签名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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 17:45:37