【发布时间】:2021-03-24 23:49:33
【问题描述】:
我通过将文件从 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 时,有没有办法通知 GCS 文件名已更改?
【问题讨论】:
标签: python google-bigquery google-cloud-storage