对于大部分系统和软件来说,上传图片是必不可少的功能,各位老哥们是否还在用原生标签<input type="file"> 去直接实现呢?  这种粗糙的方式很符合我们后端开发者们的口味,毕竟,功能实现才是核心,其他交给我们的前端和美工小姐姐就好。但俗话说的好:人靠衣装,佛靠金装。在这个“颜值”当道的时代,给用户丝滑的体验,让甲方爸爸拍手叫好,给产品经理有吹水的资本还是很重要的。 好了废话不多说,先看效果:   作为一名合格的程序员,具有“拿来主义”的思想很重要,毕竟谁能拒绝无脑ctrl+cv呢?下面的代码实现是基于imgFileupload.js 进行优化,并修复了一些bug,能更方便获取文件,和后端互动的更加自然。
CSS:imgfileupload.css
*{
margin:0;padding:0;
}
html,body{
font-family:Arial,Helvetica,sans-serif;
}
li{
list-style: none;
}
img{
border:none;display: block
}
.imgFileUploade{
width: 1024px;margin: 50px auto;
}
.imgFileUploade{
width: 100%;padding: 10px;
margin-top: -4px;
}
.imgFileUploade .header{
height: 50px;width: 100%;line-height:50px;
}
.imgFileUploade .header span{
display: block;float:left;
}
.imgFileUploade .header span.imgTitle{
line-height:50px;
}
.imgFileUploade .header span.imgTitle b{
color:red;margin:0 5px;line-height: 57px;display: block;float: right;font-size: 20px;
}
.imgFileUploade .header span.imgClick{
width: 50px;height: 50px;margin-left: 10px;cursor: pointer;
background: url(/img/addUpload.png) no-repeat center center;background-size:cover;
}
.imgFileUploade .header span.imgcontent{
color:#999;line-height: 50px;
}
.imgFileUploade .imgAll{
width: 100%; margin-top: 5px;
}
.imgFileUploade .imgAll ul:after{
visibility: hidden; display: block; font-size: 0; content: "."; clear: both; height: 0
}
.imgFileUploade .imgAll li{
width: 100px;height: 100px;border:solid 1px #ccc;margin:8px 5px;float: left;position: relative;box-shadow: 0 0 10px #eee;
}
.imgFileUploade .imgAll li img{
position: absolute;top:0;left:0;width: 100%;height: 100%;display: block;
}
.delImg{
position: absolute;top:-10px;right:-7px;width: 22px;height: 22px;background: #000;border-radius: 50%;display: block;text-align: center;line-height: 22px;color:#fff;font-weight: 700;font-style:normal;cursor: pointer;
}
.imgupBox,.imgupBox1,.imgupBox2,.imgupBox3{
border:solid 1px #ccc;
}
JS:imgFileupload.js
~(function(win){
var htmls = '<input type="file" class="imgFiles" style="display: none" accept="image/gif,image/jpeg,image/jpg,image/png,image/svg" multiple>'+
'<div class="header">'+
' <span class="imgClick">'+
' </span>'+
' <span class="imgcontent">'+
' 最多上传'+
' </span>'+
'</div>'+
'<div class="imgAll">'+
' <ul>'+
' </ul>'+
'</div>';
var ImgUploadeFiles = function(obj,fn){
var _this = this;
this.bom = document.querySelector(obj);
if(fn) fn.call(_this);
this.ready();
};
ImgUploadeFiles.prototype = {
init : function(o){
this.MAX = o.MAX || 5;
this.callback = o.callback;
this.MW = o.MW || 10000;
this.MH = o.MH || 10000;
},
ready : function(){
var _self = this;
this.dom = document.createElement('div');
this.dom.className = 'imgFileUploade';
this.dom.innerHTML = htmls;
this.bom.appendChild(this.dom);
this.files = this.bom.querySelector('.imgFiles');
this.fileClick = this.bom.querySelector('.imgClick');
this.fileBtn(this.fileClick,this.files);
this.imgcontent = this.bom.querySelector('.imgcontent');
this.imgcontent.innerHTML = '最多上传<b style="color:red">'+this.MAX+'</b>张'+_self.MW+' * '+_self.MH+'像素的图片';
},
fileBtn : function(c,f){
var _self = this;
var _imgAll = $(c).parent().parent().find('.imgAll ul');
$(c).off().on('click',function(){
$(f).click();
$(f).off().on('change',function(){
var _this = this;
_private.startUploadImg(_imgAll,_this.files,_self.MAX,_self.callback,_self.MW,_self.MH);
});
});
}
};
var _dataArr = [];
var _private = {
startUploadImg : function(o,files,MAX,callback,W,H){
_dataArr.length = 0;
var _this = this;
var fileImgArr = [];
var lens = fileArr.length;
if(lens > MAX ){
alert('不能大于'+MAX+'张');
return false;
};
var lens = $(o).find('li').length ;
if(lens >= MAX ){
alert('不能大于'+MAX+'张');
return false;
};
for(var i=0,file;file=files[i++];){
fileArr.push(file);
var reader = new FileReader();
reader.onload = (function(file){
return function(ev){
var image = new Image();
image.onload=function(){
var width = image.width;
var height = image.height;
fileImgArr.push({
fileSrc : ev.target.result,
fileName : file.name,
fileSize : file.size,
height : height,
width : width
});
};
image.src= ev.target.result;
};
})(file);
reader.readAsDataURL(file);
}
var imgTimeSlice = _this.timeChunk(fileImgArr,function(file){
if(file.width > W || file.height > H){
alert('图片不能大于'+W+'*'+H+'像素');
return false;
}
var up = new ImgFileupload(o,file.fileName,file.fileSrc,file.fileSize,callback);
up.init();
},1);
imgTimeSlice();
},
timeChunk : function(arr, fn, count) {
var obj, t;
var len = arr.length;
var start = function() {
for (var i = 0; i < Math.min(count || 1, arr.length); i++) {
var obj = arr.shift();
fn(obj)
}
};
return function() {
t = setInterval(function() {
if (arr.length === 0) {
return clearInterval(t);
}
start();
},200)
}
}
};
var ImgFileupload = function(b,imgName,imgSrc,imgSize,callback){
this.b = b;
this.imgName = imgName;
this.imgSize = imgSize;
this.imgSrc = imgSrc;
this.callback = callback;
};
var _delId = -1;
ImgFileupload.prototype.init =function() {
_delId++;
var _self = this;
this.dom = document.createElement('li');
this.dom.innerHTML =
' <img src="/img/login.gif" alt="" data-src="'+this.imgSrc +'" class="imsg">'
+' <i class="delImg">'+
' X'+
' </i>';
$(this.dom).attr({'data-delId':_delId,'data-delName':this.imgName});
$(this.b).append(this.dom);
var _Img = new Image();
_Img.src = $(this.dom).find('img').attr('data-src');
_Img.onload = function(){
$(_self.dom).find('img').attr('src',_Img.src);
}
_dataArr.push({'delId' :_delId,src : this.imgSrc});
_self.callback(_dataArr);
var _delAll = $(this.b).find('.delImg');
for(var i=0;i<_delAll.length;i++){
$(_delAll[i]).off().on('click',function(){
$(this).parent().fadeOut('slow',function(){
$(this).remove();
fileArr.splice(_delId,1);
_delId --;
});
var _deid = $(this).parent().attr('data-delId');
for(var n=0;n<_dataArr.length;n++){
if(_dataArr[n].delId == _deid){
_dataArr.splice(n,1);
}
}
_self.callback(_dataArr)
});
};
var _Imgpreview = $(this.b).find('img');
for(var k=0;k<_Imgpreview.length; k++){
$(_Imgpreview[k]).off().on('click',function(){
console.log($(this).attr('src'))
})
}
}
win.ImgUploadeFiles = ImgUploadeFiles;
})(window);
需要用到的两个图片,addUpload.png和login.gif(基本用不到)   在引入css和js后,需要在我们的js中定义一个全局变量:
<script type="text/javascript" th:inline="javascript">
var fileArr = [];
</script>
这个fileArr是个对象数组,用于记录添加或删除文件,最终我们也是从这个数组中获取文件集合,提交给后台进行上传服务器处理。当然,聪明的你也可以修改imgFileupload.js,将fileArr换成你喜欢的名字。 接下来在你的html中添加上传图片的容器
<div class="imgupBox">
最后,初始化容器,指定图片上传个数,最大像素大小即可
<script type="text/javascript">
var imgFile = new ImgUploadeFiles('.imgupBox',function(e){
this.init({
MAX : 9,
MH : 5800,
MW : 5900,
callback : function(arr){
console.log(arr)
}
});
});
</script>
需要注意的是,由于html的加载顺序,初始化容器的代码,需要在引入的css,js和div容器之后,参考顺序如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link href="imgfileupload.css" rel="stylesheet">
</head>
<body>
<div class="imgupBox"></div>
<script src="jquery.min.js"></script>
<script type="text/javascript" src="imgFileupload.js"></script>
<script type="text/javascript">
var imgFile = new ImgUploadeFiles('.imgupBox',function(e){
this.init({
MAX : 3,
MH : 5800,
MW : 5900,
callback : function(arr){
console.log(arr)
}
});
});
</script>
</body>
</html>
在选择上传图片完成后,最终的文件数组就是fileArr,我们通过ajax将文件传至后台:
function multipleFiles(){
var files = fileArr;
var length = files.length;
if(length == 0){
alert("请选择需要上传的图片!");
return;
}
var fu = new FormData();
for(var i=0;i<files.length;i++) {
fu.append("file", files[i]);
}
$.ajax({
type: "post",
url: "/uploadimgs",
data: fu,
cache: false,
contentType: false,
processData: false,
success: function (data, status) {
alert("图片上传成功!");
},
error: function (data) {
alert("图片上传失败!");
},
complete: function () {
}
});
}
后台以springBoot为例,其他框架类似的,用文件类型进行接收:
@RequestMapping("/uploadimgs")
public void defectAddUploadImgs(@RequestParam("file")MultipartFile[] files){
if (files!=null) {
for(int i=0;i<files.length;i++) {
}
}
}
至此,一个朴实无华且枯燥的图片上传功能就完成了,恭喜发现此文的你可以踩点下班了~
分享可贵,如果觉得本文不错,有帮到你的话,点个赞呗 :)
|