2

Multi多图片上传

这两天用原生徒手撸了个插件,写的不是很完美,在这里先介绍一下传统的面向过程的javascript写法,还有很多不足,希望多多指正

使用到的技术

  • 使用formDate对象:更灵活操作需要发送的表单文件
  • 使用FileReader对象:允许web应用程序异步操作本地文件
  • FileReader.readAsDataURL()将读取的文件转换为base64编码的字符串
  • FileReader.onload()文件读取时触发该方法
  • FileReader.onerror()文件读取错误时触发该方法

可以参考MDN提供的API https://developer.mozilla.org...

关键函数

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/too...


miomiomio
147 声望5 粉丝

人生昧履,砥砺而行