python - Python如何在编写和重命名文件后为谷歌云存储文件生成签名的url?
问题描述
我通过将文件从 BigQuery 导出到 Google Cloud 存储来构建文件以供下载。其中一些文件相对较大,因此它们必须在被 BigQuery 导出分片后组合在一起。
用户输入将在前端生成的文件的文件名。在后端,我正在生成一个随机的临时名称,以便我可以将文件组合在一起。
# Job Configuration for the job to move the file to bigQuery
job_config = bigquery.QueryJobConfig()
job_config.destination = table_ref
query_job = client.query(sql, job_config=job_config)
query_job.result()
# Generate a temporary name for the file
fname = "".join(random.choices(string.ascii_letters, k=10))
# Generate Destination URI
destinationURI = info["bucket_uri"].format(filename=f"{fname}*.csv")
extract_job = client.extract_table(table_ref, destination_uris=destinationURI, location="US")
extract_job.result()
# Delete the temporary table, if it doesn't exist ignore it
client.delete_table(f"{info['did']}.{info['tmpid']}", not_found_ok=True)
数据导出完成后,我通过将 blob 组合在一起来拆分文件。
client = storage.Client(project=info["pid"])
bucket = client.bucket(info['bucket_name'])
all_blobs = list(bucket.list_blobs(prefix=fname))
blob_initial = all_blobs.pop(0)
prev_ind = 0
for i in range(31, len(all_blobs), 31):
# Compose files in chunks of 32 blobs (GCS Limit)
blob_initial.compose([blob_initial, *all_blobs[prev_ind:i]])
# PREVENT GCS RATE-LIMIT FOR FILES EXCEEDING ~100GB
time.sleep(1.0)
prev_ind = i
else:
# Compose all remaining files when less than 32 files are left
blob_initial.compose([blob_initial, *all_blobs[prev_ind:]])
for b in all_blobs:
# Delete the sharded files
b.delete()
将所有文件组合成一个文件后,我将 blob 重命名为用户提供的文件名。然后我生成一个签名的 URL,该 URL 被发布到前端的 firebase 以提供文件供下载。
# Rename the file to the user provided filename
bucket.rename_blob(blob_initial, data["filename"])
# Generate signed url to post to firebase
download_url = blob_initial.generate_signed_url(datetime.now() + timedelta(days=10000))
我遇到的问题是因为使用了文件分片时使用的随机文件名。我选择使用随机文件名而不是用户提供的文件名的原因是因为可能存在多个用户使用相同(默认值)文件名提交请求的情况,因此这些边缘情况会导致文件分片问题.
当我尝试下载文件时,我得到以下返回:
<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Details>No such object: project-id.appspot.com/YMHprgIqMe000000000000.csv</Details>
</Error>
尽管我重命名了文件,但下载 URL 似乎仍在使用旧文件名。当我生成签名 URL 时,有没有办法通知 GCS 文件名已更改?
解决方案
似乎只需要重新加载 blob!
bucket.rename_blob(blob_initial, data["filename"])
blob = bucket.get(data["filename"])
# Generate signed url to post to firebase
download_url = blob.generate_signed_url(datetime.now() + timedelta(days=10000))
推荐阅读
- php - JSON.parse 在 Chrome 上出现错误,但在 Firefox 上运行良好
- swift - 这些 Swift 错误信息是什么意思?(函数声明了一个不透明的返回类型......)
- sql - SQL datediff函数数据转换错误
- html - Bootstrap:防止面板在复选框单击时折叠
- javascript - Wordpress 主题自定义:未找到 CSS 类
- java - 如何检测 Java 游戏中的按钮保持?
- docker - 来自另一个容器的 Docker 中的 mount.cifs 需要特权
- react-native - React-Native:找不到变量:缓冲区
- amazon-web-services - 我的 EC2 实例何时会被收费?
- wordpress - Wordpress 5 返回很多错误:TypeError: undefined is not an object