基於AngularJS+Bootstrap的多文件上傳與管理

1、前言

最近一個項目中須要實現多文件上傳與管理,而項目是基於bootstrap開發的,因此查了一些bootstrap文件上傳插件,最後發現仍是bootstrap-fileinput最美觀,該插件能夠實現多文件的上傳與管理(插件官方地址:http://plugins.krajee.com/file-input),具體的效果以下:javascript

 

(bootstrap-fileinput不侷限於圖片上傳,也能夠實現文件上傳,但圖片的縮略圖容易辨識,這裏就以圖片上傳爲例)css

 該插件基本的操做能夠參考:http://www.jq22.com/jquery-info5231,本文主要針對多文件管理html

 

在講該插件如何使用前,先跟你們講一下項目中關於圖片管理的需求:前端

一、  能夠上傳多個圖片java

二、  只有當點擊保存按鈕時,圖片信息才保存至數據庫jquery

三、  能夠加載已經保存到數據庫的圖片信息,並提供刪除功能angularjs

 

所以,咱們能夠規定幾個文件狀態:sql

已選擇:已經放入到插件中,但尚未上傳到服務器。如上圖中第3個圖片,該圖片下方有上傳按鈕。數據庫

已上傳:已經上傳到服務器,但圖片信息沒有保存到數據庫。如上圖中第2個圖片,該圖片下方有100%的進度條。json

已保存:圖片信息已經保存至數據庫的圖片,如上圖中第1張圖,這些圖片下方有刪除按鈕,點擊刪除時會將圖片信息從數據庫中刪除。

 

2、引入必要文件

<link href="<%=path%>/static/css/bootstrap-3.3.5/bootstrap.min.css" rel="stylesheet">
<link href="<%=path%>/static/css/bootstrap-3.3.5/fileinput.css" rel="stylesheet">

<script src="<%=path%>/static/js/jquery-1.11.3.js"></script>
<script src="<%=path%>/static/js/angularjs-1.3.9/angular.min.js"></script>
<script src="<%=path%>/static/js/bootstrap-3.3.5/bootstrap.min.js"></script>
<script src="<%=path%>/static/js/bootstrap-3.3.5/fileinput.js"></script>
<script src="<%=path%>/static/js/bootstrap-3.3.5/fileinput_locale_zh.js"></script>

 

  其中fileinput.js和fileinput_locale_zh.js都在插件待官方包中,angular.min.js和bootstrap.min.js就很少介紹了

3、多文件上傳

   首先在頁面中定義file控件:

<input id="input-images" type="file" multiple class="file-loading" accept="image/*">

  而後對該控件進行初始化,就能夠實現該組件的多文件上傳了:

	    	$("#input-images").fileinput({
	            uploadUrl: "<%=path%>" + "/album/pictureFileUpload",
	            allowedFileExtensions: ["jpg", "png", "gif"],
	            resizePreference: 'height',
	            maxFileCount: 10,
	            language: 'zh',
	            overwriteInitial: false,
	            resizeImage: true,
	        });

  固然,初始化時的屬性有不少,這裏不一一介紹了,後臺代碼(使用JFinal)以下:

	public void pictureFileUpload() {
		UploadFile uploadFile = getFile();
		renderJson("{\"link\":" + "\"/fileinput/upload/" + uploadFile.getFileName()
				+ "\"" + ",\"fileName\":\"" + uploadFile.getOriginalFileName()
				+ "\"}");
	}

  注意最後必定要返回Json,哪怕返回一個空json串(「{}」),返回的值保存在前臺的data.response中。

4、已有文件的加載與刪除

   已有文件的加載是指將服務器上已經存在的文件展現在該控件中,以實現文件管理,提供刪除功能,這主要依賴於initialPreview實現的。

  將服務器上的文件名稱和文件地址獲取以後,使用initialPreview和initialPreviewConfig完成加載和定義刪除操做:

              var initPreview = new Array();//展現元素
	    	     var initPreviewConfig = new Array();//展現設置
	    	
			$.post(
				"<%=path%>" + "/album/getPicsByAlbum", 
				{albumId : albumId}, 
				function(result) {
				for(var i=0;i<result.length;i++){
				  var pictureFile = result[i];
				    //用於展現已經上傳的圖片
			            initPreview.push("<img src='" + pictureFile.PICADDRESS 
			            		+ "' class='file-preview-image' alt='"+pictureFile.PICNAME+"' title='"+pictureFile.PICNAME+"'>");
			            var config = new Object();
			            config.caption = pictureFile.PICNAME;
			            config.url="<%=path%>" + "/album/deletePicById";
			            config.key=pictureFile.ID;
			            initPreviewConfig.push(config);
				}
				initFileInput($scope);
			        $("#input-images").fileinput('refresh', {
			        	initialPreview: initPreview,
			        	initialPreviewConfig: initPreviewConfig
			        });
			     }
			);

  點擊刪除圖標,會默認把config中待key值傳至後臺,後臺中定義deletePicById方法便可:

	public void deletePicById() {
		String picId = getPara("key");
		service.deletePicById(Integer.valueOf(picId));
		renderJson("{}");
	}

5、幾點疑問的解答

一、爲何model裏沒有屬性,卻能夠在前端展現相關屬性?

    這裏主要使用了JFinal的ActiveRecord功能,無需定義屬性和setter,getter方法,屬性值被映射在model裏的attrs裏,這個屬性是<key, value>的鍵值對,而key值就是數據庫的字段名。 特別提醒:雖然SQL語句不分區大小寫,但字段名仍是存在大小寫的,若是字段名是大寫的,那麼映射到model裏的key就是大寫的,同時JFinal的默認id爲主鍵的策略也不能生效,須要在 configPlugin中設置,以下:arp.addMapping("pictures", "ID", Picture.class),建議你們按照Java命名規範命名數據庫字段。
files.sql

二、(參考代碼)中初始化FileInput爲何要執行clear,destory操做?

    由於FileInput插件在選擇文件後,無論有沒有上傳,都會保留文件在file域中,所以再點擊時會顯示上一次選擇的文件,不符合多相冊管理的需求,本來覺得clear操做就能夠清空file域(官方文檔這麼說的),但實際操做發現並無清空,所以才調用clear,destory後再從新初始化文件上傳控件。(這一點不太肯定,但願有大神能夠指點)

三、保存時怎麼知道那些圖片須要存數據庫,這是基於什麼實現的?

$scope上有個selectedPics數組,該屬性負責保存最終那些文件會保存到數據庫。在文件選擇後會將選擇待文件信息保存到這個數組中,但hasUpload屬性爲false;在文件上傳後,會修改對應的hasUpload爲true;在上傳成功後執行刪除(尚未保存到數據庫)會從數組中移除對應的元素。有人會問,那選擇文件後不上傳直接刪除,那文件信息豈不是會佔用數據位置從而致使元素錯亂嗎?其實並不會,在fileuploaded事件中,哪些圖片已經hasUpload,是直接改數組對應位置元素的值的,而 數組座標是經過圖片所在DIV的data-fileindex屬性值得到的, 該值會一直增長,不會替補空缺值,不會由於刪除圖片而變更,正好與selectedPics數組相對應。
var idx = $("#"+previewId).attr("data-fileindex");
例如我選擇了3張圖片,此時沒有上傳,他們依次的data-fileindex爲0,1,2,當我刪除中間那個圖片並從新選擇新圖片時,那麼他們的data-fileindex就會變爲0,2,3。

6、代碼參考

文章寫得很差,太粗略了,我給你們整理了下源碼,單獨打個包,直接用eclipse導入便可實現,數據庫腳本爲files.sql(MySQL),你們多看看代碼吧。

最後本人才學AngularJS,代碼寫的不夠純熟,若有不妥之處,歡迎你們留言。

參考代碼下載地址:http://files.cnblogs.com/files/kevin19900306/fileinput.zip

相關文章
相關標籤/搜索