1. 程式人生 > >js多圖片上傳

js多圖片上傳

Multi多圖片上傳

這兩天用原生徒手擼了個外掛,寫的不是很完美,在這裡先介紹一下傳統的面向過程的javascript寫法,還有很多不足,希望多多指正

使用到的技術

  • 使用formDate物件:更靈活操作需要傳送的表單檔案
  • 使用FileReader物件:允許web應用程式非同步操作本地檔案
  • FileReader.readAsDataURL()將讀取的檔案轉換為base64編碼的字串
  • FileReader.onload()檔案讀取時觸發該方法
  • FileReader.onerror()檔案讀取錯誤時觸發該方法
    可以參考MDN提供的API https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader

關鍵函式

1.檔案變動操作
//onchange只有在檔案發生改動的時候會呼叫
inputFile.onchange = function(){
    progress = {value:0,count:this.files.length};
    for (var i = 0; i < this.files.length; i++)readerFile(this.files,i);
}
2.檔案非同步讀取
function readerFile(files,index){
    var reader = new FileReader();
    var currFile =files[index];
    reader.readAsDataURL(currFile);
    if
(checkFile(currFile,5)){ reader.onload = function(e){ currFile.result = e.target.result; fileData.push({ //格式整理 name:currFile.name, type:currFile.type, size:currFile.size, lastModified:currFile.lastModified, result:currFile.result }); createDOM(currFile) progress.value+=1
; var num = progress.value/progress.count*100; if(progress.value>=progress.count){ console.log(fileData.length+'個檔案已全部讀取完成!'); } } reader.onerror = function(){ console.log("檔案上傳失敗!"); } } }
3.檔案上傳
uploadBtn.onclick = function(){
    formData = new FormData(formDom);
    formData.set("files",JSON.stringify(fileData));
    console.log(formData)
    //封裝完成 暫無介面測試
    ajax({
        url:"",
        type:"POST",
        data:formData,
        success:function(){
            console.log("上傳成功")
        },
        error:function(){
            console.log("上傳失敗")
        }
    })
}
4.檔案格式、大小、數量、重複等檢測
function checkFile(currFile,max){
    var isLegal = true;
    if(['image/png','image/jpeg','image/jpg','image/gif'].indexOf(currFile.type)==-1){
        console.log('檔案型別只允許:png、jpg、gif');
        isLegal = false;
    }
    if(currFile.size > 2048*1024){
        console.log('檔案大小超出限制,最大允許 2 MB');
        isLegal = false;
    }
    if(fileExists(currFile.name+currFile.lastModified)){
        console.log(currFile.name+",檔案重複");
        isLegal = false;
    }
    if(fileData.length>=max){
        console.log('檔案數量超出,最多上傳'+max+'張圖片');
        isLegal = false;
    }
    return isLegal;
}
5.檔案去重(通過檔名和檔案修改時間判斷)
function fileExists(checkFlag){
    var isRepeat = false;
    console.log(fileData)
    fileData.forEach(function(f){
        if(f.name + f.lastModified === checkFlag)isRepeat = true;
    });
    return isRepeat;
}
6.建立圖片縮圖(縮圖點選刪除)(可省略)

我這裡是為了更直觀地看到上傳效果

function createDOM(currFile){
    var img = new Image();
    img.src = currFile.result;
    var li = document.createElement("li");
    li.appendChild(img);
    ul.appendChild(li);
    li.key = currFile.name + currFile.lastModified;  //給每個縮圖一個標識
    li.addEventListener("click",function(){
        var _li = this; //標識當前li元素
        ul.removeChild(this);
        fileData.forEach(function(f,i){
            if(f.name+f.lastModified == _li.key)fileData.splice(i,1);
        })
    })
}
7.上傳操作(ajax封裝)

這裡只做post的封裝

function ajax(options){
    var defaultOptions = {
        url:"",
        type:"",
        data:null,
        dataType:"json",
        success:function(){},
        error:function(){}
    }
    options = Object.assign({},defaultOptions,options);
    if(window.XMLHttpRequest){
        var xhr = new XMLHttpRequest();
    }else{
        var xhr = new ActiveXObject("Microsoft.XMLHTTP");
    }
    xhr.onreadystatechange = function(){
        if(xhr.readyState === 4){
            if(xhr.status === 200){
                options.success();
            }else{
                options.error();
            }
        }
    }
    xhr.open(options.type,options.url,true);
    xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
    xhr.send(options.data);
}

以上的程式碼是全部的js邏輯,如果想更直觀地看到效果,可將下面的html+css程式碼進行ctrl+v

/*css*/
<style type="text/css">
    *{padding:0;margin:0;}
    form{padding: 30px;width: 500px;margin: 200px auto 0;box-shadow: 0 3px 20px #ddd;}
    input{display: none;}
    span#addBtn{display: inline-block;padding: 25px;background: #00A09D;border-radius: 5px;color: white;position: relative;}
    span#addBtn::after,span#addBtn::before{content:"";width: 25px;height: 3px;background: #fff;position: absolute;top: 0;left:0;bottom: 0;right: 0;margin: auto;}
    span#addBtn::before{transform: rotate(90deg);}
    div#uploadBtn{width: 150px;margin: 20px auto 0;text-align: center;color: #fff;background: #00A09D;border-radius: 5px;padding: 10px 0;}
    ul.file-box{list-style: none;margin: 30px 0;}
    ul.file-box::after{display: block;content: "";clear: both;}
    ul.file-box li{float: left;width: 18%;margin: 10px 1% 0;border-radius: 5px;overflow: hidden;text-align: center;box-shadow: 0 3px 20px #aaa;}
    ul.file-box li img{width: 90px;height:90px;vertical-align: middle;}
    /*動畫樣式*/
    .shake-btn:hover{animation: shake .5s;}
    .bigger-btn:hover{animation: bigger .4s;}
    @keyframes shake{
        0%{transform: rotate(0deg);}
        25%{transform: rotate(5deg);}
        50%{transform: rotate(-10deg);}
        75%{transform: rotate(5deg);}
        100%{transform: rotate(0);}
    }
    @keyframes bigger{
        0%{transform: scale(1);}
        49%{transform: scale(1.1);}
        51%{transform: scale(1.1);}
        100%{transform: scale(1);}
    }
</style>


<!-- html -->
<form action="" id="fileForm" method="post">
    <!--新增圖片按鈕 start-->
    <label>
        <input type="file" name="files" multiple accept="image/jpeg,image/png,image/gif"/>
        <span id="addBtn" class="bigger-btn"></span>
    </label>
    <!--新增圖片按鈕 end-->


    <!--圖片縮圖列表 start-->
    <ul class="file-box"></ul>
    <!--圖片縮圖列表 end-->


    <!--上傳按鈕 start-->
    <div id="uploadBtn" class="shake-btn">上傳圖片</div>
    <!--上傳按鈕 end-->
</form>

好像有點多啊,這是我初步的程式碼,封裝好的完整的程式碼在我的github上
有興趣的可以去看看,大家多多批評
https://github.com/mqr123/tools/blob/master/Multi/Multi-picture-uploading.js