关于如何上传图片到ali-oss,网上和官方给的方法都有很多,我这里采用的是服务器端签名后,前端直传。这种方法一方面不会对服务器产生压力,另一方面,因为是获取签名上传,key 和 secret不会暴露,所以保证了安全性。
官方给的代码示例中没有node版本的
我这里后端用的是node中的egg框架开发的,前端使用vue+element-ui
代码如下:
1、node服务器端
主要是生成这两个字段。
policy
signature
'use strict';
const Service = require('egg').Service;
const crypto = require('crypto');
const config = {
bucket: 'xxx', // 你的bucket名称
region: 'oss-cn-hangzhou',
accessKeyId: 'xxx',
accessKeySecret: 'xxxx',
expAfter: 300000, // 签名失效时间,毫秒
maxSize: 1048576000, // 文件最大的 size
};
module.exports = class Upload extends Service {
async getOss() {
const dirPath = 'mallAdmin/'; // bucket 项目里的文件路径
const host = `https://${config.bucket}.${config.region}.aliyuncs.com`;
const expireTime = new Date().getTime() + config.expAfter;
const expiration = new Date(expireTime).toISOString();
const policyString = JSON.stringify({
expiration,
conditions: [
[ 'content-length-range', 0, config.maxSize ],
],
});
const policy = Buffer.from(policyString).toString('base64');
const signature = crypto.createHmac('sha1', config.accessKeySecret).update(policy).digest('base64');
const json = {
signature,
policy,
host,
OSSAccessKeyId: config.accessKeyId,
key: expireTime,
startsWith: dirPath,
};
return json;
}
};
2、vue前端
<template>
<div class="container">
<el-upload class="upload-component"
action=""
list-type="picture-card"
:multiple="true"
:before-upload="beforeUpload"
:http-request="upLoad"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove">
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</div>
</template>
<script>
export default {
data: () => ({
dialogImageUrl: '',
dialogVisible: false
}),
methods: {
// 移除图片
handleRemove (file, fileList) {
},
// 预览图片时调用
handlePictureCardPreview (file) {
this.dialogImageUrl = file.url
this.dialogVisible = true
},
// 文件上传之前调用做一些拦截限制
beforeUpload (file) {
const isJPG = true
const isLt2M = file.size / 1024 / 1024 < 2
if (!isLt2M) {
this.$message.error('上传图片大小不能超过 2MB!')
}
return isJPG && isLt2M
},
// 上传图片
upLoad (file) {
// 发送获取签名的请求
this.$axios //这里的axios是自己二次封装后使用的,不建议复制使用
.api('get_oss')
.get()
.then(res => {
// files上传文件的内容
// fileName 文件名
const ossInfo = res
const files = file.file
const point = files.name.lastIndexOf('.')
const suffix = files.name.substr(point) // 获取文件后缀名
const fileName = ossInfo.key + suffix
let param = new FormData() // 创建form对象
param.append('OSSAccessKeyId', ossInfo.OSSAccessKeyId)
param.append('policy', ossInfo.policy)
param.append('key', ossInfo.startsWith + fileName)
param.append('success_action_status', 200)
param.append('signature', ossInfo.signature)
param.append('file', files, fileName)
let config = {
headers: {'Content-Type': 'multipart/form-data'}
}
this.$axios
.post(ossInfo.host, param, config)
.then(res => {
this.$message({
message: '上传成功',
type: 'success'
})
let url = `${ossInfo.host}/${ossInfo.startsWith}${ossInfo.key}${suffix}`
this.showUp = false
console.log(url)
}).catch(error => {
console.log(error)
this.$message.error('上传失败')
})
})
}
}
}
</script>
3、如果产生了跨域出错问题,请前往自己的ali-oss的bucket下配置跨域设置