文件上传:OSS 通行证与图片裁切
文件上传:OSS 通行证与图片裁切的一次完整理解
前端做文件上传时,很多人一开始会以为:
选择文件 -> 上传 -> 拿到一个链接 -> 页面直接显示
但实际业务里,尤其是接入 OSS、COS、VOD 这类对象存储或视频服务后,流程通常没有这么简单。更常见的是:
选择文件 -> 本地预览 -> 获取上传通行证 -> 直传 OSS -> 拿文件标识 -> 保存业务数据
这篇文章用通用示例梳理一下:文件上传、OSS 通行证、本地预览、图片裁切、访问鉴权之间到底是什么关系。
一、上传文件到底是为了什么
前端上传文件到 OSS,很多时候不是为了立刻拿到一个永久链接,而是为了拿到一个文件标识。
常见文件标识包括:
ossname
key
fileId
它们更像数据库里的“文件身份证”。
业务接口保存的通常不是一整段 base64,也不是浏览器临时地址,而是类似这样的字段:
avatar_abc123.png
course/cover/2026/07/03/abc123.png
vod-file-id-xxxx
之后页面详情再根据这些标识,返回真正可展示的 URL。
二、预览用的数据和保存用的数据不是一回事
前端要区分两类数据。
预览用:
base64
blob URL
http URL
保存用:
ossname
key
fileId
举个例子,用户新建一条内容并上传头像。
前端选择图片后,为了马上显示效果,可能会把图片转成:
data:image/png;base64,iVBORw0KGgo...
然后直接:
<img src="data:image/png;base64,iVBORw0KGgo..." />
这个可以显示,但它不是适合长期保存的数据。
真正提交业务接口时,前端更可能提交:
{
"avatar": "avatar_abc123.png"
}
所以可以这样记:
预览是给用户看的
ossname/key 是给接口存的
三、base64、blob URL、http URL、ossname 的区别
1. base64
示例:
data:image/png;base64,iVBORw0KGgo...
特点:
图片内容直接编码在字符串中
可以直接作为 img src
常用于图片裁切后的预览
字符串比较长
可以转成 File 后上传
2. blob URL
示例:
blob:http://localhost:3000/5a1c2e...
特点:
浏览器为本地文件生成的临时地址
适合视频、PDF、原始文件本地预览
刷新页面或释放对象后会失效
不能当成长期地址保存到后端
3. http URL
示例:
https://cdn.example.com/image/avatar_abc123.png
特点:
线上资源地址
可以直接展示
是否能访问取决于权限、防盗链、签名和过期时间
4. ossname/key
示例:
avatar_abc123.png
image/avatar_abc123.png
特点:
是文件标识,不一定是完整 URL
适合保存到业务接口
通常需要后端转换成可访问 URL
四、为什么要先获取 OSS 通行证
前端不能随便往 OSS 传文件。
通常要先请求后端:
我要上传一个 png 文件,用途是头像,请给我上传参数
后端返回一套临时上传参数,可以理解成“上传通行证”。
常见字段:
host
key
ossname
policy
Signature
OSSAccessKeyId
expire
大致含义:
host:上传到哪里
key:文件在 OSS 里的完整路径
ossname:业务侧常用的文件名
policy:上传规则
Signature:签名,证明这次上传合法
OSSAccessKeyId:OSS 身份标识
expire:过期时间
接下来前端用 FormData 直传 OSS:
const form = new FormData()
form.append('OSSAccessKeyId', ossParams.OSSAccessKeyId)
form.append('policy', ossParams.policy)
form.append('Signature', ossParams.Signature)
form.append('key', ossParams.key)
form.append('success_action_status', 200)
form.append('file', file, ossParams.ossname)
await fetch(ossParams.host, {
method: 'POST',
body: form
})
这一步的重点是:
文件不是传给业务后端
而是浏览器直接传给 OSS
业务后端只负责发放临时上传参数。
五、FormData append 的第三个参数
很多人熟悉:
form.append('file', file)
但它也支持:
form.append('file', file, 'avatar_abc123.png')
第三个参数表示:
上传时这个文件在 multipart 表单里的 filename
它不是多加一个字段。
最终还是一个 file 字段,只是这个文件字段带了一个指定文件名。
六、图片裁切时发生了什么
图片裁切一般发生在前端本地。
常见流程:
用户选择图片
浏览器读取图片
裁切组件显示裁切框
用户确认裁切
canvas 生成裁切后的图片
转成 base64 或 Blob/File
页面立即预览
保存时再上传 OSS
裁切后常见代码思路:
const canvas = cropper.getCroppedCanvas()
const base64 = canvas.toDataURL('image/png')
这个 base64 可以直接预览:
<img src="data:image/png;base64,xxxx" />
也可以在上传前转成文件:
function base64ToFile(base64, filename) {
const parts = base64.split(',')
const mime = parts[0].match(/:(.*?);/)[1]
const binary = atob(parts[1])
const bytes = new Uint8Array(binary.length)
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i)
}
return new File([bytes], filename, { type: mime })
}
这里的关键点:
裁切确认不等于已经上传 OSS
本地能预览不等于已经保存成功
七、atob 和 btoa
这两个方法经常出现在 base64 处理里。
准确含义:
atob:Base64 字符串 -> 二进制字符串
btoa:二进制字符串 -> Base64 字符串
例如:
const binary = atob(base64Body)
这一步是把 base64 内容还原成二进制字符串,之后才能放进 Uint8Array,再生成 Blob/File。
注意:btoa 的输入不是任意中文字符串,而是二进制字符串。直接对中文调用 btoa 可能会报错。
八、withCredentials: false
上传到 OSS 时,经常会看到:
withCredentials: false
它的意思是:
这次请求不要携带 cookie 等身份凭证
因为 OSS 上传不靠当前业务系统的登录 cookie 判断权限,而是靠:
policy
Signature
OSSAccessKeyId
key
所以直传 OSS 时通常不需要带登录态。
九、为什么视频 src 复制出来打不开
图片、视频、合同等资源不一定都是公开资源。
有些资源访问时需要:
Referer 防盗链
临时签名参数
token
auth_key
cookie
播放鉴权
所以可能出现:
页面里 video 能播放
复制 video src 到无痕模式打不开
加上后端给的鉴权参数后能打开
播放过一次后因为缓存又能打开
尤其是视频,可能还涉及分片:
index.m3u8
segment_001.ts
segment_002.ts
segment_003.ts
看起来 video 标签只有一个 src,但播放器实际会继续请求很多资源。
如果这些资源都需要鉴权,单独复制 src 打开就很容易失败。
更稳的设计是:
数据库长期保存 fileId/key/ossname
播放前请求后端接口
后端返回当前有效的播放 URL
前端使用这个 URL 播放
过期后重新获取
十、一个通用上传流程示例
1. 用户选择图片
2. 前端用 base64 或 blob URL 预览
3. 如果需要裁切,先在前端裁切
4. 点击保存
5. 前端请求后端获取 OSS 上传参数
6. 前端用 FormData 直传 OSS
7. OSS 上传成功
8. 前端拿 ossname/key
9. 前端调用业务保存接口
10. 后续详情接口返回可展示地址
十一、最容易混淆的点
本地预览成功,不代表文件已经上传成功
上传 OSS 成功,不代表业务数据已经保存成功
拿到 ossname,不代表拿到了永久公开访问链接
http 链接能不能访问,取决于权限、防盗链、签名和过期时间
blob URL 只能当前浏览器临时用
base64 可以预览,但不适合长期保存
十二、最后的记忆方式
base64/blob:前端预览体验
ossname/key:业务保存标识
签名 URL:当前时刻可访问的临时门票
详情接口:长期展示时的数据来源
一句话总结:
文件上传不是简单地“拿链接”,而是“本地预览、获取通行证、直传存储、保存标识、按需换取可访问地址”的完整链路。
本文来自博客园,作者:jialiangzai,转载请注明原文链接:https://www.cnblogs.com/zsnhweb/p/21090663

浙公网安备 33010602011771号