“如果霍金没有去给上帝讲课,而是继续留在人间指引我们,我们可不可以在有生之年,在他的指引下穿越黑洞,到达宇宙的彼岸,去触摸那无尽的奥妙。” —— 徐卓阳
阿里云OSS前端直传的那些事儿 OSS在工作中是很常见的存储服务,之前对接过了七牛云,minio,华为云,这次对接了阿里云,那就做个分享吧。
前端直传 or 后端上传? 前端直传: 不需要经过应用服务器,直接与OSS通信,减轻了服务器压力,提高上传速度,需要确保安全性(签名,密钥)
后端上传:客户端上传至应用服务器,由服务器中转至OSS,安全性提高,可以对文件进行预处理,反之增加服务器压力,上传速度相对会变慢。
需要实现的目标
确保文件唯一性 : 用uuid生成唯一文件夹名,将文件存入,可以确保不会被同名文件覆盖
图片加上水印
图片在线预览 :二级域名绑定对应bucket
上传限制
图片在线预览 现在oss上传成功返回的图片地址,在浏览器里访问是直接下载,在官方文档里也明确了这样做的具体原因。
1 2 3 4 使用OSS默认域名或传输加速域名访问。出于数据传输安全考虑,当使用OSS默认域名或传输加速域名访问某个时间点创建的Bucket内的特定类型文件时 (例如Content-Type为text/html、image/jpeg等),OSS会强制在返回头中增加下载Header(x-oss-force-download: true和Content-Disposition: attachment)。 标准浏览器检测到Content-Disposition: attachment时,会出现强制下载而不是预览行为。关于访问指定时间创建的Bucket内特定类型文件, 导致强制下载行为时命中的x-oss-ec规则说明,请参见附录:强制下载命中的x-oss-ec规则。
官方也给出了解决方案,可以在二级域名绑定bucket达到在线访问的目的。
链接地址: https://help.aliyun.com/zh/oss/user-guide/map-custom-domain-names-5#13f82cf07dkxr
这里我带大家走一遍绑定二级域名。(已有域名并且备案通过)
进入到主域名,再进入云解析,如果你的主域名是aaa.com ,你的二级域名想命名为image ,就在这里添加为image.aaa.com ,此时你的二级域名就是www.image.aaa.com
接着拿到主机记录 和记录值 ,点击添加记录 生成一条TXT 的解析记录,
然后去阿里云OSS创建一个Bucket,在域名管理绑定刚才的二级域名就完成了。
顺便把权限开一下,读写权限,跨域设置这些很基本了,不多说。
接下来开始写代码 1 2 3 4 5 6 7 8 9 10 11 12 13 引入uuid和阿里云oss依赖包 npm install ali-oss uuid // config.js import OSS from "ali-oss"; const client = new OSS({ accessKeyId: '阿里云key', // 去阿里云的AccessKey管理查看 accessKeySecret: '阿里云密钥', // 去阿里云的AccessKey管理查看 bucket: '你的bucket', region: '创建时设置的地理位置', 去这里查看 // https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints?spm=a2c4g.11186623.0.i1#concept-zt4-cvy-5db }); export default client;
AccessKeyId :这是一个唯一的标识符,用于识别用户的身份。它通常是一个字符串,类似于一个用户名。AccessKeySecret :这是一个密钥,用于对请求进行签名,以确保请求的完整性和安全性。它类似于一个密码,不应该公开或共享Bucket :存储对象的容器(存储桶)Region :存储数据中心的位置,选择合适的Region可以优化数据访问速度和降低延迟。我们在创建Bucket时候需要选择一个Region
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 <template> <div> <el-upload class="avatar-uploader" :show-file-list="false" :before-upload="beforeImageUpload" :http-request="handleOSS" > <img v-if="imageUrl" :src="imageUrl" class="avatar" /> <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> </el-upload> <a :href="onlinePreview" class="name">在线预览</a> </div> </template> <script setup> import { onMounted, ref } from 'vue'; import { Plus } from '@element-plus/icons-vue'; import { ElMessage } from 'element-plus'; import client from './config.js'; import { v4 as uuidv4 } from 'uuid'; const imageUrl = ref(""); const onlinePreview = ref(""); const beforeImageUpload = (file) => { if (file.size / 1024 / 1024 > 2) { ElMessage.error('上传的图片不允许超过2MB!'); return false; } return true; } const handleOSS = async (rawFile) => { try { const file = rawFile.file; const subdomains = ""; // 二级域名,https://www.image.aaa.com const filePath = `/${uuidv4()}/${file.name}`; const res = await client.put(filePath, file); fileName.value = res.name; imageUrl.value = `${subdomains}/${res.name}`; onlinePreview.value = `${subdomains}/${res.name}?x-oss-process=image/resize,w_500,h_300/watermark,text_5qKo5ZWK5qKo,g_center`; console.log(onlinePreview.value) } catch (e) { console.log(e) } } </script> <style scoped> .avatar-uploader .avatar { width: 178px; height: 178px; display: block; } </style> <style> .name { font-size: 30px; } .avatar-uploader .el-upload { border: 1px dashed var(--el-border-color); border-radius: 6px; cursor: pointer; position: relative; overflow: hidden; transition: var(--el-transition-duration-fast); } .avatar-uploader .el-upload:hover { border-color: var(--el-color-primary); } .el-icon.avatar-uploader-icon { font-size: 28px; color: #8c939d; width: 178px; height: 178px; text-align: center; } </style>
其中resize 表示设置图片的尺寸,watermark 开启水印,对应的text需要转成base64,g 表示水印的位置。
最后搞定,如果小程序上传的话,最好走后端接口拿签名,不然的话,需要前端自己搭建STS服务。
我的微信公众号: 梨的前端小屋