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

如何通过Google Cloud Function网页下载GCS私有视频文件?

问题描述

我有一个返回HTML5和JavaScript页面的HTTP Google Cloud Function(GCF),页面能正常播放Google Cloud Storage(GCS)存储桶里的短视频。现在需要添加下载按钮/链接,让用户可以下载视频:

  • 公有存储桶中的视频能正常下载,但私有存储桶中的视频无法下载。
  • 测试示例页面里的公有/私有视频链接会直接播放而非触发下载;现有JS下载函数对公有视频有效,但对私有视频无效。
  • 两个存储桶都已配置CORS规则:
    gsutil cors get gs://public.awarenet.us
    [{"maxAgeSeconds": 3600,"method": ["GET"], "origin":["https://us-central1-awarenet.cloudfunctions.net"]}]
    
    gsutil cors get gs://private.awarenet.us
    [{"maxAgeSeconds": 3600,"method": ["GET"], "origin":["https://us-central1-awarenet.cloudfunctions.net"]}]
    
  • 点击“公有下载”按钮正常,响应包含Access-Control-Allow-Origin头;点击“私有下载”按钮失败,Chrome控制台提示CORS策略阻止请求(响应缺少Access-Control-Allow-Origin头),网络面板显示请求被302重定向到Google登录页面。

原因分析

  1. 私有存储桶的对象默认拒绝未授权访问,直接用对象URL请求时,GCS会返回302重定向到Google身份验证页面,这个重定向响应并没有携带你配置的CORS头,导致浏览器触发CORS拦截。
  2. JavaScript无法自动处理302重定向后的登录验证流程,也就无法获取到实际的视频资源。

解决方案

1. 生成GCS对象签名URL

私有存储桶的对象不能直接通过公开URL访问,需要在Cloud Function中为私有视频生成临时签名URL,该URL包含临时访问权限,无需用户登录即可访问。

在Cloud Function中添加生成签名URL的逻辑(以Node.js为例):

const {Storage} = require('@google-cloud/storage');
const storage = new Storage();

// 生成签名URL的函数
async function generateSignedUrl(bucketName, fileName) {
  const options = {
    version: 'v4',
    action: 'read',
    expires: Date.now() + 3600 * 1000, // 1小时后过期
  };

  const [url] = await storage.bucket(bucketName).file(fileName).getSignedUrl(options);
  return url;
}

将生成的签名URL传递给前端页面,作为私有视频的下载地址。

2. 前端实现下载逻辑

不管是公有还是私有视频,统一用以下方式触发下载,避免直接播放:

  • 方法一:使用<a>标签,添加download属性
<a href="生成的签名URL" download="视频文件名.mp4">私有视频下载</a>
  • 方法二:用JavaScript动态创建下载链接(适合需要自定义逻辑的场景)
function downloadVideo(url, fileName) {
  const a = document.createElement('a');
  a.href = url;
  a.download = fileName;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
}

3. 验证CORS配置

确保私有存储桶的CORS规则允许GCF的域名发起GET请求,你当前的配置已经满足要求,但如果签名URL的请求仍有问题,可以检查是否包含HEAD方法(部分浏览器会先发送OPTIONS预检请求),可以更新CORS规则:

# 编辑cors.json文件
echo '[
  {"maxAgeSeconds": 3600,
   "method": ["GET", "HEAD", "OPTIONS"],
   "origin":["https://us-central1-awarenet.cloudfunctions.net"]
  }
]' > cors.json

# 应用到私有存储桶
gsutil cors set cors.json gs://private.awarenet.us

关键注意事项

  • 签名URL的有效期要合理设置,避免过长导致安全风险。
  • Cloud Function需要拥有storage.objects.get和storage.objects.signUrl权限,确保服务账号有对应的IAM角色(如Storage Object Viewer + Storage Object Signer)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 17:05:51