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