js ueditor 直連 七牛雲 上傳圖片 ,無需後臺交互,通過自定義工具欄按鈕實現

    最近做的是一個前後臺分離的項目,而Ueditor上傳圖片是要與服務器後臺交互,所以一直找一個簡單的方法,能讓ueditor直接上傳圖片到七牛雲,然後ueditor引入圖片鏈接就好了。上傳圖片不經過自己應用後臺,提高系統的吞吐量。

該效果的原理是使用自定義工具觸發js上傳到七牛雲,並添加到ueditor的內容中

效果演示

    使用自定義工具欄上傳圖片到七牛雲,先看看演示效果

工具欄上添加了一個插入圖片的按鈕,這個按鈕的圖片是上傳到到七牛雲的,點擊這個按鈕

出現選擇圖片按鈕,點擊打開,這時候就可以看到圖片添加到編輯內容區域了

並且這個圖片鏈接是引用七牛雲的

 

實現原理

    首先是添加自定義工具欄按鈕,需要編寫以下幾步代碼:

    注:不要用min.js,否則無法修改源碼

(1)啓用自定義按鈕:在ueditor.config.js配置中添加自定義的按鈕名稱,這裏我取名爲qiniuimage

(2)添加自定義按鈕到ueditor,在ueditor.all.js中搜btnCmds即可:

(3)添加自定義按鈕的註釋:注意看文件和對應位置,我都做了標註

(4)自定義按鈕圖片定義:注意看文件路徑,ueditor.css,這裏我複製了一下之前圖片按鈕的樣式,這裏說明一下,ueditor所有的工具欄按鈕圖片在一個png裏面,默認都加上了background-image屬性,所以我直接用了現成的圖片,直接指定工具欄所處位置就好了,這裏的 -380px 0px 就是image圖片標識的位置

(5)添加自定義按鈕的相應js事件:這裏解釋一下,在ueditor.all.js裏面通過UE.commands['按鈕名']添加按鈕響應事件,我直接複製了打印(print)的事件代碼修改了下

好,至此按鈕添加完成了,現在已經可以在ueditor上看到新定義的按鈕了。可以看到,我的js就是觸發上傳按鈕的單擊事件,我界面上還有個上傳按鈕(因爲我界面有多個上傳圖片的地方),具體內容參看後文

注意:必須引用非min.js,即ueditor.all.js

 

講到這裏我普及一下三個點,針對於對七牛雲原生api不熟的

(1) 七牛雲上傳必須關聯一個input爲file的按鈕,你選擇這個按鈕,上傳完會觸發七牛FileUploaded事件,重要的事情說三遍,

必須關聯一個input爲file的按鈕,必須關聯一個input爲file的按鈕,必須關聯一個input爲file的按鈕

(2)上面我這個app.putDataBuffer是我的一個自定義方法,請無視,主要用來保存我的想要添加圖片的位置的

(3)流程圖

 

下面來講解一下如何上傳圖片到到七牛雲,首先根據官方sdk文檔,copy了一下代碼,並對其中關鍵部分做了修改

	scope.uploader = Qiniu.uploader({
		runtimes: 'html5,flash,html4', // 上傳模式,依次退化
		browse_button: 'pickfiles', // 上傳選擇的點選按鈕,必需
		// 在初始化時,uptoken,uptoken_url,uptoken_func三個參數中必須有一個被設置
		// 切如果提供了多個,其優先級爲uptoken > uptoken_url > uptoken_func
		// 其中uptoken是直接提供上傳憑證,uptoken_url是提供了獲取上傳憑證的地址,如果需要定製獲取uptoken的過程則可以設置uptoken_func
		uptoken: app.getDataBuffer("qiniuToken"), // uptoken是上傳憑證,由其他程序生成
		// uptoken_url: '/uptoken',         // Ajax請求uptoken的Url,強烈建議設置(服務端提供)
		//uptoken_func: function(){    // 在需要獲取uptoken時,該方法會被調用
		//    // do something
		//    return uptoken;
		//},
		get_new_uptoken: false, // 設置上傳文件的時候是否每次都重新獲取新的uptoken
		// downtoken_url: '/downtoken',
		// Ajax請求downToken的Url,私有空間時使用,JS-SDK將向該地址POST文件的key和domain,服務端返回的JSON必須包含url字段,url值爲該文件的下載地址
		unique_names: true, // 默認false,key爲文件名。若開啓該選項,JS-SDK會爲每個文件自動生成key(文件名)
		// save_key: true,                  // 默認false。若在服務端生成uptoken的上傳策略中指定了sava_key,則開啓,SDK在前端將不對key進行任何處理
		domain: 'http://p357khip9.bkt.clouddn.com', // bucket域名,下載資源時用到,必需
		container: 'publish-add-button', // 上傳區域DOM ID,默認是browser_button的父元素
		max_file_size: '100mb', // 最大文件體積限制
		flash_swf_url: 'path/of/plupload/Moxie.swf', //引入flash,相對路徑
		max_retries: 3, // 上傳失敗最大重試次數
		dragdrop: true, // 開啓可拖曳上傳
		drop_element: 'container', // 拖曳上傳區域元素的ID,拖曳文件或文件夾後可觸發上傳
		chunk_size: '4mb', // 分塊上傳時,每塊的體積
		auto_start: true, // 選擇文件後自動上傳,若關閉需要自己綁定事件觸發上傳
		//x_vars : {
		//    查看自定義變量
		//    'time' : function(up,file) {
		//        var time = (new Date()).getTime();
		// do something with 'time'
		//        return time;
		//    },
		//    'size' : function(up,file) {
		//        var size = file.size;
		// do something with 'size'
		//        return size;
		//    }
		//},
		init: {
			'FilesAdded': function(up, files) {
				plupload.each(files, function(file) {
					// 文件添加進隊列後,處理相關的事情
				});
			},
			'BeforeUpload': function(up, file) {
				// 每個文件上傳前,處理相關的事情
			},
			'UploadProgress': function(up, file) {
				// 每個文件上傳時,處理相關的事情
			},
			'FileUploaded': function(up, file, info) {
				//獲取圖片鏈接
				var domain = up.getOption('domain');
				var res = JSON.parse(info.response);
				var sourceLink = domain + "/" + res.key;
				if(app.getDataBuffer("picposition") == 'mainPic'){
					scope.view.item.mainPic = sourceLink;
				}
				
				if(app.getDataBuffer("picposition") == 'content'){
					scope.editor.execCommand('inserthtml','<img src="'+sourceLink+'"/>');  
				}
				
			},
			'Error': function(up, err, errTip) {
				debugger;
				//上傳出錯時,處理相關的事情
			},
			'UploadComplete': function() {
				//隊列文件處理完畢後,處理相關的事情
			},
			'Key': function(up, file) {
				// 若想在前端對每個文件的key進行個性化處理,可以配置該函數
				// 該配置必須要在unique_names: false,save_key: false時才生效
				var key = "";
				// do something with key here
				return key
			}
		}
	});

注:這個scope.uploader只是爲了保存qiniu的實例,你這麼寫 var myQiniu = new Qiniu(...)效果完全一樣

其中有幾個必須字段需要說明下(也就是需要自己定義的地方),

browse_button: 上傳圖片按鈕的ID,點擊該按鈕觸發圖片上傳

container:上傳圖片按鈕的容器ID(父級domid),點擊該dom觸發圖片上傳

uptoken:上傳憑證,由後臺生成。這裏有兩個生成策略,一個是一次生成長期使用(我採用的,獲取後存在全局中),一個是每個憑證是一次性使用,每次請求都要重新生成。這個根據你們自己的後臺邏輯傳值

get_new_uptoken:false表示每次上傳不重新獲取上傳憑證

unique_names:true若開啓該選項,JS-SDK會爲每個文件自動生成key(文件名)

domain:bucket域名,下載資源時用到,必需,這個是後臺給的,相當於名字

這裏貼一下我的dom結構

<li v-show="!item.mainPic" id="publish-add-button" class="pics addbutton">
	<img src="../../images/pic_add.png" @click="openFileDialog" />
	<input type="file" style="display: none" id="pickfiles" accept="image/jpeg,image/jpg,image/png" />
</li>

 

最後一個關鍵的就是上傳成功回調事件了

 

'FileUploaded': function(up, file, info) {
				//獲取圖片鏈接
				var domain = up.getOption('domain');
				var res = JSON.parse(info.response);
				var sourceLink = domain + "/" + res.key;
				if(app.getDataBuffer("picposition") == 'mainPic'){
					scope.view.item.mainPic = sourceLink;
				}
				
				if(app.getDataBuffer("picposition") == 'content'){
					scope.editor.execCommand('inserthtml','<img src="'+sourceLink+'"/>');  
				}
				
			},

這裏獲取的sourceLink就是圖片的全路徑了,app.getDataBuffer和app.putDataBuffer是獲取和設置全局變量的地方。前文我也說過,我界面上有多處上傳圖片的地方,我用了一個全局變量保存我這次添加圖片的位置,然後觸發添加圖片的按鈕,最後上傳成功後判斷圖片應該添加到哪個位置。

最後使用ueditor的exeCommand函數,插入了一段html,這個html就是img

至此,所有功能完成。

總結

    通過觸發ueditor自定義按鈕方式,觸發自定義上傳圖片代碼,完美繞過ueditor的上傳圖片機制(與後臺交互),使得圖片上傳不消耗應用服務器的流量,提高了系統的吞吐量和性能。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章