腾讯云OSS阿里云COS的对象存储都是参考的AWS的S3对象存储:都是提供基本存储服务然后加上一整套收费服务,这其中就有一个面向前端的服务:文件直传/简单上传
就是用户端直接把文件传到OSS中节省服务器带宽,在加钱购买文件审核功能节省自己处理:例如:网站用户修改头像,服务端提供一个签名地址,用户通过签名地址上传后端可以获得OSS存储地址 OSS文档: help.aliyun.com/zh/oss/user…
生成并返回Post签名和PostPolicy 这个签名会规定各种参数(参数经过签名上传需要符合要求)
{
"accessid": "LTAI5tF3Zt...",
"host": "https://oss-cn-shanghai.aliyuncs.com",
"policy": "eyJleHBpcmF0aW9uIjoiM....",
"signature": "3Qy3bEOlTXKWgd+kzZO+zPd4ZLY=",
"expire": 1743080451,
"callback": "eyJjYWxsYmFja1VybCI6Im...",
"dir": "image/2025-3-27/"
}
前端一般会从后端拿到 以上内容的签名,如果你发现dir 记住后面要考
我们再看一下policy参数经过base64_decode查看一下里面内容:
{
"expiration": "2025-03-27T21:00:51Z",
"conditions": [
["starts-with", "$key", "image/2025-3-27/"],
["content-length-range", 0, 9048576000],
["in", "$content-type", ["image/jpg", "image/png", "image/jpeg" ]]
]
}
- expiration 是有效期在这时间传文件即可
- conditions[] 约束条件
- ["starts-with", "key 就行)
- ["in", "$content-type",[]] 代表你上传的文件类型mime要在那几个类型之中,你只要记住一个就行了
大的要来了,经过跟阿里云工单切磋,确认阿里云是不处理的文件MIME类型的,你本地文件是什么类型浏览器全靠浏览器帮你侦测,你也可以自己指定:对没错后端的签名里面指定了只能上传图片,但是OSS告诉你说,你文件什么类型可以自己写,写成在in里面那几就行了
那么直接以阿里云控制台工单系统为例:他也用了他们自家产品
本来是找它头像上传的,头像会被公开访问,后面发现阿里云关闭了头像上传
https://smartservice.console.aliyun.com/service/create-ticket 是阿里云的工单图片上传地址,在地址栏目上直接 fetch方式复制,你就拿到了需要上传的所有签名。
既然传文件不会一个一个上传,一般直接帮做好的网站目录准备好
在阿里云控制台页面选一个空白处大一些的div 右键最后 存储为全局对象这时候控制台temp1就是这个对象了
temp1.addEventListener('dragover', (e) => {
e.preventDefault(); // 防止浏览器默认打开文件的行为
});
temp1.addEventListener("drop", (e)=>{
e.preventDefault();
const transfer = e.dataTransfer
const files = transfer.files;
console.log(11,transfer)
// blobParts 是一个数组,可以包含 ArrayBuffer、Blob、String 或其他二进制数据
// 自己改装一下 把文件类型改为 OSS签名指定的类型
const newBlob = new Blob(blobParts, { type: 'application/octet-stream' });
});
控制台执行上面伪代码,将文件夹拖到这个div 松开,就能看到打印的出来的文件目录与文件 自行处理一下
最后一步直传任意文件到控制台
// 这是第一步拿到阿里云的oss签名
fetch("https://help.aliyun.com/zh/oss/user-guide/simple-upload", { method: "GET"}).then(r=>r.json()).then(res=>{
// 这里拼装一下表单 阿里云给的也是前缀
let formData = new FormData();
formData.append("success_action_status", "200");
formData.append("policy", res.data.Data.DataInfo.Policy);
formData.append("x-oss-signature", res.data.Data.DataInfo.Signature);
formData.append("x-oss-signature-version", "OSS4-HMAC-SHA256");
formData.append("x-oss-credential", res.data.Data.DataInfo.x_oss_credential);
formData.append("x-oss-date", res.data.Data.DataInfo.x_oss_date);
// 这里文件名 跟你目录/文件名一直 比如你首页 inde.html index.css
formData.append("key", res.data.Data.DataInfo.Key + `file.name`);
formData.append("x-oss-security-token", res.data.Data.DataInfo.security_token);
// 这个file 使用 newBlob 改造过的 OSS 不会验证这玩意
formData.append("file", `fileBlob`);
// file 必须为最后一个表单域
})
最后上传完成:得到的网站 首页地址为https://gts-workorder-prod.oss-cn-zhangjiakou.aliyuncs.com/20250327/a276-49e4-b43d-8cf9f822/index.html
最后总结:其实上面我并没有真的去上传,毕竟违法的事情,而且这个接口也不限制你传任何文件。我只是没想到OSS开放了文件直传做了文件类型判断,它真的就是做着看的。
如果你已经用了OSS这种对象存储如何规避:
- 关闭公开访问,你网站文章用户头像所有的为了方便使用了公开访问的,要立刻整改,采用每个链接都
签名+有效期的方式进行访问 - 如果有前端直传功能,需要
整改关闭:采用文件传服务器,服务器校验之后再传OSS存储,不关闭前端直传功能别人照样可以图片当视频/exe文件/apk包传。 - 1和2 都采用了,那么你不就是传统网站上传+CDN了吗?对的,没错 改回传统开发,+DCDN分发静态文件方式。如果有音视频处理需求,使用OSS回源网站静态目录的方式。
- 如果网站还在初期:建议采用专业云存储方案
七牛,又拍云这类专门做存储服务的厂商,他们默认强制侦测文件类型杜绝图片当视频上传。
用OSS是为了方便,但是当安全审查报告甩在你桌上的时候。有你哭的时候,技术选型要乘早,能用就行,我跟代码一个能跑就行,迟早火葬场~
但行好事 莫问前程 拜了个拜~