本文介紹了Vue2.0利用vue-resource上傳文件到七牛,分享給大家,希望對(duì)大家有幫助
關(guān)于上傳,總是有很多可以說道的。
16年底,公司項(xiàng)目番茄表單的前端部分,開始了從傳統(tǒng)的jquery到vue 2.0的徹底重構(gòu)。但是上傳部分,無論是之前的傳統(tǒng)版本,還是Vue新版本,都是在使用著FileAPI這款優(yōu)秀的開源庫,只是進(jìn)行了簡(jiǎn)單的directive化。為什么呢?因?yàn)榧嫒菪浴]辦法,公司項(xiàng)目不等同于個(gè)人項(xiàng)目,必須要考慮大多數(shù)瀏覽器。否則,上傳部分完全可以利用Vue-Resource以及FormData來拋開對(duì)FileAPI的依賴。這讓我深感遺憾,幸好這個(gè)簡(jiǎn)單的遺憾在個(gè)人博客Vue化重構(gòu)的時(shí)候得以彌補(bǔ)。
上傳流程
圖不重要看文字
input[type="file"] change事件觸發(fā)后,先去(如果是圖片,可以同時(shí)通過FileReader以及readAsDataURL將圖片預(yù)覽在頁面上)后臺(tái)請(qǐng)求七牛的上傳token,將拿到的token和key以及通過change傳遞過來的files一起append到formData中。然后將formData通過post傳遞給七牛,七牛在處理后將返回真正的文件地址
獲取token
const qiniu = require('qiniu') const crypto = require('crypto') const Config = require('qiniu-config') exports.token = function*() { //構(gòu)建一個(gè)保存文件名 //這里沒有處理文件后綴,需要自己傳遞過來,然后在這里處理加在key上,非必須 const key = crypto.createHash('md5').update(((new Date()) * 1 + Math.floor(Math.random() * 10).toString())).digest('hex') //Config 七牛的秘鑰等配置 const [ACCESS_KEY, SECRET_KEY, BUCKET] = [Config.accessKey, Config.secretKey, Config.bucket] qiniu.conf.ACCESS_KEY = ACCESS_KEY qiniu.conf.SECRET_KEY = SECRET_KEY const upToken = new qiniu.rs.PutPolicy(BUCKET + ":" + key) try { const token = upToken.token() return this.body = { key: key, token: token } } catch (e) { // throw error } } //假設(shè)api 地址是 /api/token
上傳組件 upload.vue
<template> <label class="mo-upload"> <input type="file" :accept="accepts" @change="upload"> <slot></slot> </label> </template> <style lang="scss"> .mo-upload { display: inline-block; position: relative; margin-bottom: 0; input[type="file"] { display: none; } .mo-upload--label { display: inline-block; position: relative; } } </style> <script> export default { name : 'MoUpload', props : { accepts : { //允許的上傳類型 type : String, default : 'image/jpeg,image/jpg,image/png,image/gif' }, flag : [String, Number], //當(dāng)前上傳標(biāo)識(shí),以便于在同一個(gè)監(jiān)聽函數(shù)中區(qū)分不同的上傳域 maxSize : { type : Number, default : 0 //上傳大小限制 }, }, methods: { upload (event) { let file = event.target.files[0] const self = this const flag = this.flag if (file) { if (this.maxSize) { //todo filter file } //filter file, 文件大小,類型等過濾 //如果是圖片文件 // const reader = new FileReader() // const imageUrl = reader.readAsDataURL(file) // img.src = imageUrl //在預(yù)覽區(qū)域插入圖片 const formData = new FormData() formData.append('file', file) //獲取token this.$http.get(`/api/token/`) .then(response => { const result = response.body formData.append('token', result.token) formData.append('key', result.key) //提交給七牛處理 self.$http.post('https://up.qbox.me/', formData, { progress(event) { //傳遞給父組件的progress方法 self.$emit('progress', parseFloat(event.loaded / event.total * 100), flag) } }) .then(response => { const result = response.body if (result.hash && result.key) { //傳遞給父組件的complete方法 self.$emit('complete', 200 , result, flag) //讓當(dāng)前target可以重新選擇 event.target.value = null } else { self.$emit('complete', 500, result, flag) } }, error => self.$emit('complete', 500, error.message), flag) }) } } } } </script>
父組件調(diào)用
<template> <section> ... <figure class="upload-preview"> <img :src="thumbnail" v-if="thumbnail"/> </figure> <mo-upload flag="'thumbnail'" @complete="uploadComplete" @progress="uploadProgress"> <a>選擇圖片文件<i class="progress" :style="{width:progress + '%'}"></i></a> </mo-upload> ... </section> </template> <script> import MoUpload from 'upload' export default { components : { MoUpload, }, data () { return { thumbnail : null, progress : 0 //上傳進(jìn)度 } }, methods : { uploadProgress (progress, flag) { //這里可以通過回調(diào)的flag對(duì)不同上傳域做處理 this.progress = progress < 100 ? progress : 0; }, uploadComplete(status, result, flag) { if (status == 200) { // this.thumbnail = `domain.com/${result.key}` //七牛域名 + 返回的key 組成文件url } else { //失敗處理 } }, } } </script>
小結(jié)
相比于FILEApi 或者其他上傳組件,這種方法代碼量最小。但是缺點(diǎn)也是顯而易見的,大量html5 API的使用,勢(shì)必會(huì)回到兼容性這個(gè)老大難上來,慎重的選擇性使用吧‘
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com