上傳圖片,多圖上傳,預覽功能,js原生無依賴


最近很好奇前端的文件上傳功能,因為公司要求做一個支持圖片預覽的圖片上傳插件,所以自己搜了很多相關的插件,雖然功能很多,但有些地方不能根據公司的想法去修改,而且需要依賴jQuery或Bootstrap庫,所以我就想學下圖片上傳的原理,試着做一個原生無依賴,而且足夠靈活的圖片上傳插件。話不多說,開整。

1. 大體思路

1.1 首先我們需要考慮用戶如何使用我們的插件。

用戶引入插件代碼后,只需要像下面這樣,設置一些參數,然后執行一個方法就生成一個圖片上傳組件。

<div id="upload"></div>  // 這是用來生成圖片上傳組件的div
<script>
// 設置參數
var options = {
    path: '/',    // 上傳圖片時指定的地址路徑,類似form變淡的action屬性
    onSuccess: function (res) {    // 上傳成功后執行的方法,res是接收的ajax響應內容
        console.log(res);  
    },
    onFailure: function (res) {    // 上傳失敗后執行的方法,res是接收的ajax響應內容
        console.log(res);
    }
}
// 執行生成圖片上傳插件的方法, 第一個參數是上面提到的准備生成組件的div選擇器,第二個參數是設置的組件信息,執行方法后返回一個函數指針,指向執行上傳功能的函數,通過把執行上傳功能的函數暴露出來,用戶就可以自己控制何時上傳圖片了。
var upload = tinyImgUpload('#upload', options);  
</script>

1.2 代碼設計

我們需要思考用戶如何引入我們的插件代碼。
插件代碼應該分為兩個文件,一個CSS文件(tinyImgUpload.css),用於定義組件的基本樣式,此外用戶可以根據自己的想法自己DIY樣式,另一個是控制功能邏輯的js文件(tinyImgUpload.js)。用戶引入這兩個文件后,就可以實現圖片上傳組件了。

2. 具體實現

具體實現的時候,主要涉及到兩個地方,一個是讀取本地文件,實現圖片上傳前可以預覽的功能,一個是圖片上傳功能。

2.1 讀取本地文件實現預覽

這里用到了html5的File API,使用這個API可以在客戶端驗證上傳的文件類型,限制文件大小,當然,在這里我們主要用到FileReader接口來讀取文件,Filereader.readAsDataURL()返回的事件對象的result屬性就是將文件編碼為base64的數據地址,類似下面這樣的,把他賦值給src屬性,圖片就顯示出來了。
base64圖片的樣子
具體代碼如下,完整代碼可以從這里下載(tinyImgUpload.js

// 預覽圖片
//處理input選擇的圖片
function handleFileSelect(evt) {
    var files = evt.target.files;

    for(var i=0, f; f=files[i];i++){
        // 過濾掉非圖片類型文件
        if(!f.type.match('image.*')){
            continue;
        }
        // 過濾掉重復上傳的圖片
        var tip = false;
        for(var j=0; j<(ele.files).length; j++){
            if((ele.files)[j].name == f.name){
                tip = true;
                break;
            }
        }
        if(!tip){
            // 圖片文件綁定到容器元素上
            ele.files.push(f);

            var reader = new FileReader();
            reader.onload = (function (theFile) {
                return function (e) {
                    var oDiv = document.createElement('div');
                    oDiv.className = 'img-thumb img-item';
                    // 向圖片容器里添加元素
                    oDiv.innerHTML = '<img class="thumb-icon" src="'+e.target.result+'" />'+
                                    '<a href="javscript:;" class="img-remove">x</a>'

                    ele.insertBefore(oDiv, addBtn);
                };
            })(f);

            reader.readAsDataURL(f);
        }
    }
}
// input#img-file-input是一個隱藏的上傳圖片的input控件,當選擇圖片的時候會觸發change事件
document.querySelector('#img-file-input').addEventListener('change', handleFileSelect, false);

2.2 上傳圖片

2.2.1 准備文件對象

上傳文件之前,我們需要考慮如何保存用戶已經選擇的文件對象,由於用戶可能多次選擇,也可能在上傳之前又刪除了幾個圖片,所以需要有一個地方實時保存圖片信息,並且要和預覽的圖片保持同步,預覽顯示有哪幾張圖片,這個地方就存儲幾張圖片。我采用的方式是將文件信息組裝成一個數組,然后綁定到組件元素(#img-container)的自定義屬性上,上面代碼中的“ele.files.push(f)”做的就是這件事。

2.2.2 文件對象我們准備好后,下一步就是上傳了

ajax是不能直接上傳文件對象的,我們可以通過FormData對象,FormData是XMLHttpRequest Level 2添加的一個新接口,使用一系列的鍵值對來模擬一個完整的表單,然后使用XMLHttpRequest異步發送這個"表單"。具體代碼如下。

// 上傳圖片
function uploadImg() {
    var xhr = new XMLHttpRequest();
    var formData = new FormData();

    for(var i=0, f; f=ele.files[i]; i++){
        formData.append('files', f);
    }

    xhr.onreadystatechange = function (e) {
        if(xhr.readyState == 4){
            if(xhr.status == 200){
                options.onSuccess(xhr.responseText);
            }else {
                options.onFailure(xhr.responseText);
            }
        }
    }

    xhr.open('POST', options.path, true);
    xhr.send(formData);
}

2.3 設置樣式

我們寫了一個基本的布局樣式作為默認樣式,用戶可以根據自己的需求進行DIY。這里是完整的樣式文件(tinyImgUpload.css )。
基本的效果圖如下。
demo樣式
如果我們想觸發上傳圖片,可以把tinyImgUpload('#upload', options)返回的upload方法綁定到一個按鈕上,監聽點擊事件。

<button class="submit">submit</button>
<script>
document.getElementsByClassName('submit')[0].onclick = function (e) {
    upload();
}
</script>

這樣當我點擊圖片的時候,圖片就會上傳,交給服務器端處理了。
上傳按鈕
上傳按鈕
服務器接收的圖片
服務器接收的圖片

為了測試圖片上傳好不好用,我自己搭建了一個圖片接收的服務器,使用的是node.js,通過multer實現,如果大家感興趣可以點擊這里

3 總結

圖片上傳的關鍵部分就是如何讀取本地文件實現預覽,以及通過FormData對象構造一個表單對象實現ajax異步上傳文件。目前這個插件的功能還不夠完善,我把它放到了Github上(https://github.com/gitwd/tinyImgUpload),后續會慢慢優化,歡迎大家提出寶貴意見。

4 參考目錄

https://www.html5rocks.com/en/tutorials/file/dndfiles/
http://codecloud.net/9276.html
http://www.zhangxinxu.com/wordpress/2011/09/基於html5的可預覽多圖片ajax上傳/
https://cnodejs.org/topic/50ce2bbb637ffa415589a50f


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM