轉載請標明出處:http://blog.csdn.net/lmj623565791/article/details/31513065

上一篇已經實現了這個專案的整體的HTML和CSS:

HTML5 CSS3 經典案例:無外掛拖拽上傳圖片 (支援預覽與批量) (一)

這篇部落格直接在上篇的基礎上完成,最終效果:

效果圖1:

效果圖2:

好了,請允許我把圖片貼了兩遍,方便大家看效果了~

可以看出我們的圖片的li的html其實還是挺複雜的,於是我把html文件做了一些修改:

<span style="font-size:12px;"><body>

<div id="uploadBox">
</div> <div id="template" class="hidden">
<li>
<img src=""/>
<span class="progress"></span>
<span class="percentage"></span>
</li>
</div>
</body></span>

可以看到我把li的顯示,獨立寫到了一個div#template,預設是hidden的,這樣做的好處是什麼呢?避免我們每上傳一個檔案,在js中出現大量的建立元素與賦屬性的程式碼,一般設計比較複雜的html元素的生成,建議使用這種方式,可以簡化程式碼,也利於我們程式碼的後期維護。

Js程式碼:

<span style="font-size:12px;">/**
* User: zhy
* Date: 14-6-16
* Time: 下午11:06
*/
var ZhangHongyang = {};
ZhangHongyang.html5upload = (function ()
{
var _ID_UPLOAD_BOX = "uploadBox";
var _CLASS_PROGRESS = "progress";
var _CLASS_PERCENTAGE = "percentage"; var _tip_no_drag = "將檔案拖拽至此區域,即可上傳!";
var _tip_drag_over = "釋放滑鼠立即上傳!"; var _uploadEle = null; /**
* 初始化物件與事件
* @private
*/
function _init()
{
_uploadEle = document.getElementById(_ID_UPLOAD_BOX);
_uploadEle.ondragenter = _onDragEnter;
_uploadEle.ondragover = _onDragOver;
_uploadEle.ondragleave = _onDragLeave;
_uploadEle.ondrop = _onDrop;
_setStatusNoDrag(); }; /**
* 正在拖拽狀態
* @private
*/
function _setDragOverStatus()
{
if (_checkContatinsElements())return;
_uploadEle.innerText = _tip_drag_over;
_uploadEle.style.border = "2px dashed #777";
$(_uploadEle).css({lineHeight: $(_uploadEle).height() + "px"});
} /**
* 初始化狀態
* @private
*/
function _setStatusNoDrag()
{
if (_checkContatinsElements())return;
_uploadEle.innerText = _tip_no_drag;
_uploadEle.style.border = "2px dashed #777";
$(_uploadEle).css({lineHeight: $(_uploadEle).height() + "px"});
} /**
* 上傳檔案
* @private
*/
function _setDropStatus()
{ if (_checkContatinsElements())return;
_uploadEle.innerText = "";
_uploadEle.style.border = "1px solid #444";
$(_uploadEle).css({lineHeight: "1em"});
$(_uploadEle).append("<ul></ul>"); }; /**
* 判斷是否已經上傳檔案了
* @private
*/
function _checkContatinsElements()
{
return !!$(_uploadEle).find("li").size(); }
/**
* 當ondragenter觸發
* @private
*/
function _onDragEnter(ev)
{
_setDragOverStatus();
}
/**
* 當ondargmove觸發
* @private
*/
function _onDragOver(ev)
{
//ondragover中必須組織事件的預設行為,預設地,無法將資料/元素放置到其他元素中。
ev.preventDefault(); }
/**
* 當dragleave觸發
* @private
*/
function _onDragLeave(ev)
{
_setStatusNoDrag();
} /**
* ondrop觸發
* @private
*/
function _onDrop(ev)
{
//drop 事件的預設行為是以連結形式開啟,所以也需要阻止其預設行為。
ev.preventDefault();
_setDropStatus(); //拿到拖入的檔案
var files = ev.dataTransfer.files;
var len = files.length;
for (var i = 0; i < len; i++)
{
//頁面上顯示需要上傳的檔案
_showUploadFile(files[i]);
}
}
/**
* 頁面上顯示需要上傳的檔案
* @private
*/
function _showUploadFile(file)
{
var reader = new FileReader();
// console.log(file)
// console.log(reader); //判斷檔案型別
if (file.type.match(/image*/))
{
reader.onload = function (e)
{
var formData = new FormData(); var li = $("#template li").clone();
var img = li.find("img");
var progress = li.find(".progress");
var percentage = li.find(".percentage");
percentage.text("0%");
img.attr("src", e.target.result);
$("ul", $(_uploadEle)).append(li);
$(_uploadEle).find("li").size() == 10 && $(_uploadEle).width(($(_uploadEle).width() + 8) + "px").css("overflow", "auto");
formData.append("uploadFile", file); //上傳檔案到伺服器
_uploadToServer(formData, li, progress, percentage); };
reader.readAsDataURL(file);
}
else
{
console.log("此" + file.name + "不是圖片檔案!");
}
} /**
* 上傳檔案到伺服器
* @private
*/
function _uploadToServer(formData, li, progress, percentage)
{
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost:8080/strurts2fileupload/uploadAction", true);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest', 'Content-Type', 'multipart/form-data;'); //HTML5新增的API,儲存了上傳過程中的資訊
xhr.upload.onprogress = function (e)
{
var percent = 0;
if (e.lengthComputable)
{
//更新頁面顯示效果
percent = 100 * e.loaded / e.total;
progress.height(percent );
percentage.text(percent + "%");
percent >= 100 && li.addClass("done");
}
};
xhr.send(formData);
} //把init方法公佈出去
return{
init: _init } })();
</span>

註釋寫得很詳細,這次沒有直接使用字面量建立物件,因為我不希望使用者可以訪問所有的方式和變數,使用了簡單的閉包,可以看出幾乎所有的方法和變數都是_開頭,是因為我認為它們是私有的,我也沒有公佈出來,唯一公佈的就是init方法,供使用者呼叫。整體方法也使用了名稱空間,這樣和其他夥伴寫的js基本不做造成變數相同的問題。


上面的js中用到了HTML FileApi,這裡介紹一下:

1、File物件也就是我們上面使用的:
File
  1. lastModifiedDate: Thu
    Dec 26 2013 18:45:08 GMT+0800 (中國標準時間)
  2. name: "yt_key.png"
  3. size: 45524
  4. type: "image/png"
  5. webkitRelativePath: ""
  6. __proto__: File

可以看到包含上面的一些屬性,也就是說,如果使用支援html5的瀏覽器,給input=type設定onchange事件,使用者選擇圖片或者檔案後,就可以做出圖片的顯示或者檔案大小和型別的判斷。


2、FileReader主要用於非同步讀取檔案內容,注意是非同步的,上例我們使用了它的readAsDataURL的方法,關於DataUri的知識可以自己去百度下。
另外還提供了:readAsText用於讀取文字;readAsArrayBuffer和readAsBinaryString方法;
還提供了一些事件:onloadstart, onload, onprogress ,onerror , onloaded , onabort 有興趣的可以去一個一個檢視。

最後頁面呼叫,大功告成:

<span style="font-size:12px;">    <script type="text/javascript" src="jquery-1.8.3.js"></script>
<script type="text/javascript" src="js/html5upload.js"></script> <script type="text/javascript"> window.onload = function ()
{
ZhangHongyang.html5upload.init();
}
; </script></span>

歡迎大家指點~

原始碼點選下載

版權宣告:本文為博主原創文章,未經博主允許不得轉載。