【前端实战】大文件上传打满ECS公网带宽?基于OBS预签名的前端直传工程解法
在传统的单体或微服务架构中,文件上传的请求链路通常是浏览器 -> 七层网关/Nginx -> 后端业务服务 -> 云存储 (OBS)。这种模式下,大文件会长时间占用 ECS 实例的内存缓冲池与公网出网带宽,一旦遇到并发上传,整个 API 接口将被彻底拖垮。
标准的云原生工程解法是:剥离数据流与控制流,后端仅充当“发证机关”,让前端拿到临时通行证后直接将数据写到底层 OBS。
1. 后端生成临时预签名 URL(Pre-signed URL)
业务应用层不接收任何文件流数据,只对外暴露一个获取上传凭证的轻量级 API。在这个接口中,利用云厂商的 SDK,结合私钥(AK/SK)在内存中计算出一个带有严格过期时间(如 5 分钟)与操作限制的直传 URL:
# Python 后端生成临时上传 URL 示例
from obs import ObsClient
obs_client = ObsClient(access_key_id='AK', secret_access_key='SK', server='obs.cn-north-4.myhuaweicloud.com')
def get_upload_credential(file_name):
# 生成一个仅允许 PUT 操作、有效期 300 秒的临时直传链接
res = obs_client.createSignedUrl(
method='PUT',
bucketName='my-prod-assets',
objectKey=f"uploads/{file_name}",
expires=300
)
return {"upload_url": res.actualSignedRequestHeaders}
# 将此 URL 返回给前端
2. 前端直连底层云存储
前端拿到临时 URL 后,绕过所有业务网关,直接向目标存储桶发起 HTTP PUT 请求推送二进制流。
// 前端直接利用原生 fetch 或 axios 将 File 对象推向 OBS
async function uploadDirectlyToOBS(file, signedUrl) {
const response = await fetch(signedUrl, {
method: 'PUT',
body: file, // 直接将文件流作为 body
headers: {
'Content-Type': file.type
}
});
if (response.ok) {
console.log("直传成功,无需经过业务后端!");
}
}
3. 配置存储桶的跨域资源共享(CORS)
因为前端网页的域名(如 [www.myapp.com](https://www.myapp.com))与华为云 OBS 的域名(如 obs.cn.myhuaweicloud.com)不同,浏览器会发起基于 OPTIONS 方法的跨域预检请求。必须在 OBS 控制台中提前配置 CORS 规则,否则直传会被浏览器安全拦截:
-
允许的来源 (AllowedOrigin):
[https://www.myapp.com](https://www.myapp.com) -
允许的方法 (AllowedMethod):
PUT -
允许的头域 (AllowedHeader):
*
总结:
基于预签名 URL 的客户端直传架构,是富媒体业务上云的核心标配。它将高消耗的 I/O 数据流彻底从 ECS 计算节点中剥离,不仅单次上传速度得到物理级提升,更让业务网关免受大文件并发造成的内存 OOM 威胁,实现了存储与计算的真正解耦。
- 点赞
- 收藏
- 关注作者
评论(0)