一、Qiniu-JavaScript-SDK介紹
基於 JS-SDK 可以方便的從瀏覽器端上傳文件至七牛雲存儲,並對上傳成功后的圖片進行豐富的數據處理操作。
JS-SDK 兼容支持 H5 File API 的瀏覽器,在低版本瀏覽器下,需要額外的插件如 plupload,JS-SDK 提供了一些接口可以結合插件來進行上傳工作。
Qiniu-JavaScript-SDK 為客戶端 SDK,沒有包含 token
生成實現,為了安全,token
建議通過網絡從服務端獲取,具體生成代碼可以參考服務端 SDK 的文檔。
1、參考文檔
官方API文檔:JavaScript SDK
基於七牛 API 開發的前端 JavaScript SDK 源碼地址:https://github.com/qiniu/js-sdk
2、引入(NPM安裝)
NPM 的全稱是 Node Package Manager,是一個 NodeJS 包管理和分發工具,已經成為了非官方的發布 Node 模塊(包)的標准。
$ npm install qiniu-js
二、vue項目實現
創建七牛上傳組件:/src/components/chart/QiniuUpload.vue
下面代碼中集成了上傳進度條,及上傳完成提示,還添加了已上傳文件的文件名顯示:
<template> <div class="ft-plant-upload-button" :class="boxClass"> <Button class="upload-btn" type="ghost" icon="ios-cloud-upload-outline" :disabled="percent > 0 && percent < 100" @click="zh_uploadFile">{{qiniuUploadDesc}}</Button> <div class="progress-wraper" v-if="showProgress"> <div class="progress" v-if="percent > 0 && percent < 100"> <div class="progress-bar" role="progressbar" aria-valuemin="0" aria-valuemax="100" :style="{width: percent+'%'}"> </div> </div> <div class="precent" v-if="percent > 0 && percent < 100"> {{percent || 0 }}% </div> </div> <div class="file-name" v-else> {{fileName}} </div> <input type="file" ref="evfile" @change="zh_uploadFile_change" style="display:none"> <input type="hidden" :value="qiniuKey"> </div> </template> <script> import * as qiniu from "qiniu-js" export default { name: "QiniuUpload", props: { // 子組件的props選項 qiniuUploadDesc: { type: String, default: '上傳文件' }, classroomUpload: { default: '未知classroom' }, filetype: { type: String }, boxClass: { type: String, default: '' }, fileName: { type: String } }, data(){ return { queryInfo: { limit: 10, offset: 0, }, token: "", qiniuKey: "", percent: 0, percentText: "", showProgress: false } }, methods: { beforeImageUpload(file) { // 限制圖片格式和大小 const isPng = file.type === "image/png"; const isJpeg = file.type === "image/jpeg"; const isJpg = file.type === "image/jpg"; const isLt2M = file.size / 1024 / 1024 < 2; if (!isPng && !isJpeg && !isJpg) { this.$showDialog("警告信息", "上傳圖片只能是 jpg、png、jpeg 格式!"); return false; // 等同於retrun false; 不執行 } else if (!isLt2M) { this.$showDialog("警告信息", "上傳圖片大小不能超過2MB!"); return false; } else { return true; } }, httpGetList: function () { var self = this; this.$httpGet(this.$http, "users/dataController/getUploadToken", this.$trimJson(self.queryInfo), function (ret) { console.log('ret', ret.token); return ret.token; }); }, //選擇上傳文件 zh_uploadFile(){ this.$refs.evfile.click(); }, //選擇文件后觸發的事件 zh_uploadFile_change(evfile){ if (evfile){ this.showProgress = true; // 顯示上傳過程 //后端獲取token this.getQiniuToken().then(res=>{ console.log('res', res); var uptoken = res; var userno = this.$sessionUser.fetch().userno; var timestamp = Date.parse(new Date()); // 時間戳 var file = evfile.target.files[0]; //Blob 對象,上傳的文件 var key = ""; if (this.filetype === "idCodeImg") { // 身份證照片 if (this.beforeImageUpload(file)) { key = this.filetype + '/U' + userno + 'T' + timestamp + '/' + file.name; } else { return; } } else if (this.filetype === "cardImg") { // 證件照片 if (this.beforeImageUpload(file)) { key = this.filetype + '/U' + userno + 'T' + timestamp + '/' + file.name; } else { return; } } else{ // 課堂附件 this.$emit('change', file.name); key = this.filetype + '/' + this.classroomUpload + '/U' + userno + 'T' + timestamp + '.' + file.name.split('.').pop(); // 上傳后文件資源名,以設置的 key 為主,如果 key 為 null 或者 undefined,則文件資源名會以 hash 值作為資源名。 } let config = { useCdnDomain: true, // 表示是否使用 cdn 加速域名,為布爾值,true 表示使用,默認為 false。 region: qiniu.region.z1 // 上傳域名區域(z1為華北),當為 null 或 undefined 時,自動分析上傳域名區域 }; let putExtra = { fname: "", // 文件原文件名 params: {}, // 放置自定義變量: 'x:name': 'sex' mimeType: null // 限制上傳文件類型,為 null 時表示不對文件類型限制;限制類型放到數組里: ["image/png", "image/jpeg", "image/gif"] }; // observable是一個帶有 subscribe 方法的類實例 var observable = qiniu.upload(file, key, uptoken, putExtra, config); var subscription = observable.subscribe({ // 上傳開始 next: (result) => { // 接收上傳進度信息,result是帶有total字段的 Object // loaded: 已上傳大小; size: 上傳總信息; percent: 當前上傳進度 console.log(result); // 形如:{total: {loaded: 1671168, size: 2249260, percent: 74.29856930723882}} this.percent = result.total.percent.toFixed(0); }, error: (errResult) => { // 上傳錯誤后失敗報錯 console.log(errResult) }, complete: (result) => { // 接收成功后返回的信息 console.log(result); // 形如:{hash: "Fp5_DtYW4gHiPEBiXIjVsZ1TtmPc", key: "%TStC006TEyVY5lLIBt7Eg.jpg"} this.qiniuKey = result.data.key; this.showProgress = false; this.$emit('key', this.qiniuKey); this.$emit('url', result.data.url); } }) }) } }, getQiniuToken(){ return new Promise((resolve, reject)=>{ var self = this; this.$httpGet(this.$http, "users/dataController/getUploadToken", this.$trimJson(self.queryInfo), function (ret) { console.log('ret', ret.token); resolve(ret.token); }); }) } }, mounted() { this.$pageInit(); this.fileToken = this.$sessionUser.fetch().fileToken; } } </script>
2、在父組件中引入七牛上傳組件
使用props傳遞屬性到子組件。這樣可以拼接出比較復雜的文件名(key: 文件資源名)。
<template> <div class="app-content"> <section class="section"> <v-breadcrumb></v-breadcrumb> <div class="section-body"> <div class="row"> <div class="col-lg-12"> <div class="card"> <div class="card-header"> <h4>編輯/添加招生學生</h4> </div> <div class="card-body"> <div class="row"> <div class="col-md-6"> <div class="form-group row"> <label for="idCardFront" class="col-md-4 col-form-label">身份證正面上傳(頭像)</label> <QiniuUpload id="idCardFront" filetype="idCodeImg" :qiniuUploadDesc="'上傳圖片'" :boxClass="'add-idImg1'" @url="setFrontUrl" :fileName="queryInfo.idImg1.split('/').pop()"> <template slot="uploadTitle"> </template> </QiniuUpload> </div> <div class="form-group row"> <label for="idCardBack" class="col-md-4 col-form-label">身份證反面上傳(國徽)</label> <QiniuUpload id="idCardBack" filetype="idCodeImg" :qiniuUploadDesc="'上傳圖片'" :boxClass="'add-idImg2'" @url="setBackUrl" :fileName="queryInfo.idImg2.split('/').pop()"> <template slot="uploadTitle"> </template> </QiniuUpload> </div> </div> <div class="col-md-6"> <div class="form-group row"> <label for="cardType" class="col-md-3 col-form-label">學歷證件</label> <div class="col-md-5 m-t-5 m-b-5"> <Enums type="card_type" id="cardType" v-model="queryInfo.cardType" placeholder="請選擇證件類型"></Enums> </div> </div> <div class="form-group row"> <label for="idCardBack" class="col-md-3 col-form-label">學歷證件上傳</label> <QiniuUpload id="cardImg" filetype="cardImg" :qiniuUploadDesc="'上傳圖片'" :boxClass="'add-cardImg'" @url="setCardUrl" :fileName="queryInfo.cardImg.split('/').pop()"> <template slot="uploadTitle"> </template> </QiniuUpload> </div> </div> </div>