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

如何利用getSignedUrl从Chrome浏览器上传大文件至Google Cloud Storage?

嘿,这个问题我太熟了!用Google Cloud Storage的预签名(getSignedUrl)链接在Chrome这类浏览器上传大文件,其实用原生的Web API就能轻松搞定,还能实现可靠的分块上传避免中断。下面一步步给你讲清楚:

基础单文件上传(适合中等大小文件)

如果你的文件不算特别大(比如几十MB以内),直接用Fetch API就能快速完成上传:

  1. 先通过页面的文件选择器获取要上传的文件对象:
// 假设页面上有个id为"file-upload"的<input type="file">
const fileInput = document.getElementById('file-upload');
const targetFile = fileInput.files[0];
  1. 调用Fetch发送PUT请求到预签名URL,重点要保证请求头的Content-Type和生成预签名URL时指定的完全一致:
async function uploadSingleFile(signedUrl, file) {
  try {
    const uploadResponse = await fetch(signedUrl, {
      method: 'PUT',
      body: file,
      headers: {
        'Content-Type': file.type // 必须和生成getSignedUrl时的Content-Type匹配!
      }
    });

    if (uploadResponse.ok) {
      console.log('文件上传成功!');
      // 这里可以添加上传成功后的页面逻辑,比如提示用户
    } else {
      console.error(`上传失败,状态码:${uploadResponse.status},信息:${uploadResponse.statusText}`);
    }
  } catch (error) {
    console.error('上传请求出错:', error);
  }
}

// 调用方法:传入你的预签名URL和选中的文件
uploadSingleFile('你的预签名URL', targetFile);
大文件分块上传(推荐,应对超大型文件)

对于几百MB甚至GB级的大文件,一次性上传很容易因为网络波动、超时导致失败,这时候用分块上传更可靠。GCS支持分块上传,每个块至少5MB(最后一块可以更小),步骤如下:

  1. 定义分块大小,比如设置为10MB(可根据网络情况调整):
const CHUNK_SIZE = 10 * 1024 * 1024; // 10MB
const totalChunks = Math.ceil(targetFile.size / CHUNK_SIZE);
  1. 循环上传每个分块,通过Content-Range头告诉GCS当前块的范围,GCS会自动合并所有块:
async function uploadLargeFile(signedUrl, file) {
  const chunkSize = 10 * 1024 * 1024;
  const totalChunks = Math.ceil(file.size / chunkSize);

  for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
    const startByte = chunkIndex * chunkSize;
    // GCS的Content-Range是闭区间,所以endByte要减1
    const endByte = Math.min(startByte + chunkSize, file.size) - 1;
    const currentChunk = file.slice(startByte, endByte + 1);

    try {
      const chunkResponse = await fetch(signedUrl, {
        method: 'PUT',
        body: currentChunk,
        headers: {
          'Content-Type': file.type,
          'Content-Range': `bytes ${startByte}-${endByte}/${file.size}`
        }
      });

      if (chunkResponse.status === 308) {
        // 308是正常的续传状态码,表示当前块上传成功,继续传下一块
        console.log(`第${chunkIndex + 1}/${totalChunks}块上传完成`);
      } else if (chunkResponse.ok) {
        // 最后一块上传完成,整个文件合并成功
        console.log('所有块上传完成,文件已成功保存到GCS!');
        break;
      } else {
        throw new Error(`第${chunkIndex + 1}块上传失败:${chunkResponse.statusText}`);
      }
    } catch (error) {
      console.error('分块上传出错:', error);
      // 这里可以添加重试逻辑,比如针对失败的块重新上传几次
      return;
    }
  }
}

// 调用分块上传方法
uploadLargeFile('你的预签名URL', targetFile);
关键注意事项

这些细节一定要注意,不然很容易踩坑:

  • 预签名URL有效期:大文件上传耗时久,生成URL时别设太短的过期时间(比如至少1小时以上),避免上传到一半URL失效。
  • Content-Type严格匹配:生成预签名URL时指定的Content-Type,和上传请求头里的必须完全一致,否则会返回403/400错误。
  • 跨域配置(CORS):如果你的网页域名和GCS域名跨域,必须给存储桶配置CORS规则,允许你的域名发起PUT请求,并且允许Content-Type、Content-Range这些请求头。比如用gsutil配置的规则示例:
    [
      {
        "origin": ["https://你的网页域名.com"],
        "method": ["PUT"],
        "responseHeader": ["Content-Type", "Content-Range"],
        "maxAgeSeconds": 3600
      }
    ]
    
  • 上传进度监听:如果要给用户展示上传进度,可以用XMLHttpRequest的progress事件,或者给Fetch搭配ReadableStream实现。比如XMLHttpRequest的示例:
    function uploadWithProgress(signedUrl, file) {
      const xhr = new XMLHttpRequest();
      xhr.open('PUT', signedUrl);
      xhr.setRequestHeader('Content-Type', file.type);
    
      // 监听上传进度
      xhr.upload.addEventListener('progress', (event) => {
        if (event.lengthComputable) {
          const progressPercent = (event.loaded / event.total) * 100;
          console.log(`上传进度:${progressPercent.toFixed(2)}%`);
          // 这里可以更新页面上的进度条DOM
        }
      });
    
      xhr.onload = () => {
        xhr.status === 200 ? console.log('上传成功!') : console.error('上传失败:', xhr.statusText);
      };
      xhr.onerror = () => console.error('上传请求出错');
    
      xhr.send(file);
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:43:16