如何用Python将4GB等大文件上传至存储桶(含FastAPI对接GCP场景)
大视频上传至GCS且避免POST请求长期挂起的Python/FastAPI可行方案
除你已知的分块上传方案外,还有两种更常用的低负载实现方案,具体如下:
方案1:GCS签名URL直传(最推荐)
该方案完全避免后端承接文件流,全程不会出现后端请求长期挂起的问题
- 核心逻辑:FastAPI仅提供签名URL生成接口,响应时间在毫秒级;前端拿到签名URL后直接将视频上传至GCS,上传完成后主动回调后端标记上传状态即可
- 实现要点:
- 依赖
google-cloud-storage库完成签名生成,URL有效期可根据视频大小设置为15分钟到2小时不等 - 核心代码示例:
from google.cloud import storage from fastapi import FastAPI app = FastAPI() storage_client = storage.Client() bucket = storage_client.get_bucket("你的GCS桶名称") @app.post("/generate-upload-url") def generate_upload_url(file_name: str, content_type: str): blob = bucket.blob(file_name) signed_url = blob.generate_signed_url( version="v4", expiration=3600, # 有效期1小时,可按需调整 method="PUT", content_type=content_type ) return {"upload_url": signed_url}
- 依赖
方案2:FastAPI后台任务异步上传
适合需要后端先接收文件、做预处理后再上传到GCS的场景
- 核心逻辑:前端上传文件到FastAPI后端,后端接收完成后立即返回
202 Accepted响应,把上传GCS的逻辑丢到后台任务中异步执行,前端不需要等待上传到GCS的过程 - 实现要点:
- 用FastAPI原生的
BackgroundTasks组件实现异步任务,超大文件可以先写入本地临时磁盘,后台任务读取本地文件上传完成后自动删除临时文件 - 需要提前配置FastAPI的
FILE_UPLOAD_MAX_MEMORY_SIZE参数,避免大文件上传被拦截 - 核心逻辑示例:
import os from fastapi import FastAPI, File, UploadFile, BackgroundTasks from google.cloud import storage app = FastAPI() storage_client = storage.Client() bucket = storage_client.get_bucket("你的GCS桶名称") def upload_to_gcs(file_path: str, gcs_blob_name: str): blob = bucket.blob(gcs_blob_name) blob.upload_from_filename(file_path) # 上传完成后删除本地临时文件 os.remove(file_path) @app.post("/upload-video", status_code=202) async def upload_video(background_tasks: BackgroundTasks, file: UploadFile = File(...)): # 先把文件写入本地临时目录 temp_file_path = f"/tmp/{file.filename}" with open(temp_file_path, "wb") as f: f.write(await file.read()) # 把上传任务丢到后台执行 background_tasks.add_task(upload_to_gcs, temp_file_path, file.filename) return {"message": "文件接收成功,正在上传到存储桶"}
- 用FastAPI原生的
方案3:分块上传(已知方案补充)
适合单文件大小超过10G的超大视频场景
- 核心逻辑:前端把视频拆分为固定大小的块(一般设为8MB-100MB),逐块上传到后端或直接传到GCS,所有块上传完成后调用接口通知GCS合并块
- 优势:支持断点续传,网络中断后不需要重传全部文件,每个块的上传请求都是短时间请求,不会出现长期挂起问题
内容的提问来源于stack exchange,提问作者Hassen Ammar
相关产品推荐
相关产品推荐

