昨天問了一下element團隊,他們還沒有試過用element-ui的upload組件傳圖片到七牛雲
我試了一天發現沒問題,同時覺得七牛並沒有一個前端後端流程都演示到的demo,於是再次記錄一波
流程
- 後端配置好七牛相關的accessKey
- 後端構建好上傳策略,用來生成消費次數只有1次的上傳Token
- 後端暴露一個api,返回上面的Token
- 前端在上傳前請求後端的api獲得上傳Token
- 前端上傳完畢,獲得七牛返回的圖片地址
前置
七牛相關
- 公鑰和私鑰
- 一個對象存儲Bucket
- 一個數據處理隊列Pipeline
- Bucket的一個外鏈域名
對應配置字段
qiniuAccessKey: '',
qiniuSecretKey: '',
qiniuBucketHost: '',
qiniuBucketName: '',
qiniuPipeline: ''
文檔
- element upload
- 七牛前端api
- 夠隱蔽了,我翻了兩小時都沒翻到,還以爲七牛沒暴露上傳的api呢,最後是同事指出地址的
- 上傳策略簡介
- 上傳策略api文檔
- 多媒體圖像高級處理api文檔
- 數據處理隊列api
- 這個api是用來查看數據處理的出錯信息的,因爲七牛的控制檯在失敗時只會給你看“處理失敗”這個四個字
後端
let qiniu = require("qiniu")
qiniu.conf.ACCESS_KEY = qiniuAccessKey;
qiniu.conf.SECRET_KEY = qiniuSecretKey;
let fops = 'imageMogr2/format/webp'
const policy = (name, fileName) => {
let encoded = new Buffer(`${qiniuBucketName}:webp/${fileName}`).toString('base64')
let persist
if (qiniuPipeline !== '') {
persist = {
persistentOps: `${fops}|saveas/${encoded}` ,
persistentPipeline: qiniuPipeline
}
} else {
persist = {}
}
return Object.assign({},persist,{
scope: name,
deadline: new Date().getTime() + 600,
})
}
const getQiniuTokenFromFileName = (fileName) => {
let key = `${qiniuBucketName}:${fileName}`
let putPolicy = new qiniu.rs.PutPolicy2(policy(key, fileName));
let upToken = putPolicy.token();
return {
upToken,
key,
bucketHost,
supportWebp: qiniuPipeline !== ''
};
}
module.exports = getQiniuTokenFromFileName;
如上代碼,導出一個參數爲文件存儲根路徑的函數,再用它新增一個路由即可
主要調用了qiniu.rs.PutPolicy2這個api,傳入一個上傳策略對象,生成一個消費次數只有一次的圖片上傳token,供給前端上傳
上傳策略只需要指定文件根路徑scope以及deadline,除此之外,上面的代碼還另外調用了多媒體圖像高級處理接口,將圖片異步轉爲webp格式,並在最終導出一個是否支持webp的supportWebp字段。
這裏有一個坑,persistentOps字段要求是base64編碼,然而其他的api又要求url編碼,坑了我半天
前端
HTML
<el-dialog title="圖片上傳" v-model="isUploadShow">
<el-upload
action="//up.qbox.me/"
type="drag"
:thumbnail-mode="true"
:on-success="handleSuccess"
:before-upload="beforeUpload"
:data="form"
>
<i class="el-icon-upload"></i>
</el-upload>
</el-dialog>
七牛up.qbox.me域名支持http和https上傳。api文檔裏並沒有寫這個,而是寫在Q&A裏的
JS
data () {
return {
isUploadShow: false, // 是否顯示upload組件
supportWebp: false, // 是否支持webp
bucketHost: '', // 上傳圖片的外鏈域名
form: {}
}
}
vue2組件的data如上
beforeUpload (file) {
let curr = moment().format('YYYYMMDD').toString()
let prefix = moment(file.lastModified).format('HHmmss').toString()
let suffix = file.name
let key = encodeURI(`${curr}/${prefix}_${suffix}`)
return api.getImageToken({ key }).then(response => {
this.bucketHost = response.bucketHost
this.supportWebp = response.supportWebp
this.form = {
key,
token: this.upToken
}
})
},
通過getImageToken這個api,將上傳token請求下來,並獲得圖片外鏈的地址,以及是否支持webp,如果支持webp,上傳成功後就給圖片鏈接根路徑加上webp/前綴。
handleSuccess (response, file, fileList) {
let key = response.key
let name = file.name
let prefix = this.supportWebp ? 'webp/' : ''
let img = `![${name}](${this.bucketHost}/${prefix}${encodeURI(key)})`
},