阿里云OSS WEB直传配置上传Token凭证
2024-01-06 20:25:12
背景介绍
Vditor可能是目前能找到的最完善的WEB端MarkDown开源编辑器了,coderbbb的MarkDown编辑器就是使用的Vditor。编辑器在日常使用中比较常见的一个需求是:当我们在Vditor中粘贴站外图片或直接上传本地图片的时候,我们希望图片直接上传到阿里云OSS上,不经过我们的业务服务器转发,这样可以有效降低业务服务器的带宽占用,同时还能提高图片的上传速度。
遇到的问题
通常情况下,使用阿里云OSS WEB直传的方式(阿里云WEB直传OSS文档),需要web浏览器先请求业务服务器拿到一个上传token之类的凭证,然后拿着这个凭证和图片数据请求阿里云OSS的域名,完成上传。这种情况下,就要求图片上传的方法有一个前置方法,即上传前请求的方法。同时,因为该方法需要请求业务服务器,所以是异步操作,返回结果是一个promise,上传方法根据这个promise的结果再决定要不要上传。
但是,我们研究Vditor的文档发现,并没有可以直接拿来用的上传前检查的方法。不过幸运的是,上传配置中,有一个File的配置项,本来是用作上传前文件处理的,支持Promise,可以拿来实现我们的上传前Token等数据拉取。
代码演示
Vditor上传配置代码options.upload如下:
getUploadConfig()
{
let that = this;
return {
url: '666',
multiple: false,
fieldName: 'file',
headers: this.imgUploadInfo.headers,
setHeaders: function () {
let headers = that.imgUploadInfo.headers;
return headers;
},
linkToImgUrl: SER + "/api/user/img/pullWebImg",
linkToImgFormat: function (responseText) {
let result = JSON.parse(responseText);
if (result.status === true) {
return '{"msg": "","code": 0,"data" : {"originalURL": "' + result.data.originalUrl + '","url": "' + result.data.url + '"}}';
} else {
return '{"msg": "' + result.msg + '","code": -1,"data" : {"originalURL": "","url": ""}}';
}
},
file: function (files) {
//该方法请求业务服务器,把需要携带的各种Token凭证拉取下来,再赋值给extraData。
return that.getUploadImgSig(files);
},
format: function (files, res) {
let result = JSON.parse(res);
if (result.code === 200) {
let filename = result.data.ossFileDO.uuid + ".jpg";
let filepath = result.data.cdnHost + "/" + result.data.ossFileDO.thumbPath;
return '{"msg": "","code": 0,"data": {"errFiles": [],"succMap": {"' + filename + '": "' + filepath + '"}}}';
} else {
return '{"msg": "上传失败","code": -1,"data": {"errFiles": [],"succMap": {}}}';
}
},
extraData:{}
};
}
上面的代码中,我们通过this.getuploadImgSig方法来请求业务服务器,拉取各种Token凭证等自定义数据。这里还有一个操作可能会用到,就是Vditor的很多配置项在初始化编辑器的时候就设置好了,后期我们如何才能修改呢?比如我们上传图片前,请求业务服务器拿到了图片路径、签名凭证等等,想把这些信息追加到上传请求的Header或body form data中,应该如何操作呢?
vditor对象.vditor.options.upload.extraData={...}其中,Vditor对象就是初始化编辑器的时候,new vditor的结果。通过类似的方法,就可以随心所欲的动态修改Vditor的配置项了。
附上this.getuploadImgSig的代码,仅供参考,因为每个人设计的逻辑不一样。
getUploadImgSig: function (files) {
let that = this;
return this.$ajax.get(this.$host + "/api/uploadBefore", {
params: {
ext: ".jpg",
}
}).then(function (res) {
const result = res.data;
if (result.code === 200) {
that.imgUploadInfo.host = 'https://' + result.data.host;
that.imgUploadData.key = result.data.path;
that.imgUploadData.policy = result.data.policy;
that.imgUploadData.OSSAccessKeyId = result.data.accessId;
that.imgUploadData.signature = result.data.signature;
that.imgUploadData.callback = result.data.callBack;
that.contentEditor.vditor.options.upload.url = that.imgUploadInfo.host;
that.contentEditor.vditor.options.upload.extraData = that.imgUploadData;
return Promise.resolve(files);
} else {
return Promise.reject(result.msg);
}
}).catch(function (err) {
return Promise.reject(err);
});
}
服务端代码
阿里云OSS WEB直传的服务端代码,可以参考阿里云WEB直传服务端代码,里面包含了常见的各种服务端语言的案例。这里友情提示一个安全漏洞,就是WEB直传阿里云OSS的时候,可以通过x-oss-object-acl来控制上传文件的权限。因为前端的数据可被任意修改,所以一定要在业务服务器的上传成功回调中,重设文件权限~否则有可能你计划的文件权限是public-read或private,实际却被前端改成了public-write-read。
0