關(guān)于如何上傳圖片到ali-oss,網(wǎng)上和官方給的方法都有很多牍氛,我這里采用的是服務(wù)器端簽名后,前端直傳烟阐。這種方法一方面不會(huì)對(duì)服務(wù)器產(chǎn)生壓力搬俊,另一方面,因?yàn)槭谦@取簽名上傳蜒茄,key 和 secret不會(huì)暴露唉擂,所以保證了安全性。
官方給的代碼示例中沒有node版本的
我這里后端用的是node中的egg框架開發(fā)的扩淀,前端使用vue+element-ui
代碼如下:
1楔敌、node服務(wù)器端
主要是生成這兩個(gè)字段。
policy
signature
'use strict';
const Service = require('egg').Service;
const crypto = require('crypto');
const config = {
bucket: 'xxx',
region: 'oss-cn-hangzhou',
accessKeyId: 'xxx',
accessKeySecret: 'xxx',
expAfter: 300000, // 簽名失效時(shí)間驻谆,毫秒
maxSize: 1048576000, // 文件最大的 size
};
module.exports = class Upload extends Service {
async getOss() {
const dirPath = 'mallAdmin/'; // bucket 項(xiàng)目里的文件路徑
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片段
<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>
- js
<script>
export default {
data: () => ({
dialogImageUrl: '',
dialogVisible: false
}),
methods: {
// 移除圖片
handleRemove (file, fileList) {
},
// 預(yù)覽圖片時(shí)調(diào)用
handlePictureCardPreview (file) {
this.dialogImageUrl = file.url
this.dialogVisible = true
},
// 文件上傳之前調(diào)用做一些攔截限制
beforeUpload (file) {
const isJPG = true
const isLt2M = file.size / 1024 / 1024 < 2
if (!isLt2M) {
this.$message.error('上傳圖片大小不能超過 2MB!')
}
return isJPG && isLt2M
},
// 上傳圖片
upLoad (file) {
// 發(fā)送獲取簽名的請(qǐng)求
this.$axios //這里的axios是自己二次封裝后使用的,不建議復(fù)制使用
.api('get_oss')
.get()
.then(res => {
// files上傳文件的內(nèi)容
// 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() // 創(chuàng)建form對(duì)象
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胜臊、如果產(chǎn)生了跨域出錯(cuò)問題勺卢,請(qǐng)前往自己的ali-oss的bucket下配置跨域設(shè)置