整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

在线文件拖拽上传插件—DropzoneJS

在线文件拖拽上传插件—DropzoneJS

DropzoneJS是一个提供文件拖拽上传并且提供图片预览的开源类库, 零依赖且高度可定制

官网和Github

官方文档:https://www.dropzonejs.com/

中文版本:http://wxb.github.io/dropzonejs.com.zh-CN/dropzonezh-CN/#installation

Github: https://github.com/enyo/dropzone/

下载和安装

https://raw.githubusercontent.com/enyo/dropzone/master/dist/dropzone.js

引入到我们的页面

<script src="./path/to/dropzone.js"></script>

这是官网Demo的效果, 如果你也想用到这样的效果, 可以直接到源码包的dist文件夹下样式拷贝过来。

Dropzone 不会处理你上传到服务器上面的文件. 你必须自己编写代码实现接收和保存上传的文件。

如何使用?

我们只需要创建一个class类名是dropzone的form表单元素:

<form action="/file-upload" class="dropzone" id="my-awesome-dropzone"></form>

Dropzone将查找所有的 class 属性中包含 dropzone 的表单元素, 就是这么简单, 这些上传文件将被正常处理就像这里是一段像下面这样的HTML代码:

<input type="file" name="file" />

程序化方式创建 dropzones

不是必须在form上, 你也可以通过js代码初始化一个dropzone实例

// Dropzone class:
var myDropzone=new Dropzone("div#myId", { url: "/file/post"});

或者假如你用到了jquery也可以这样写

// jQuery
$("div#myId").dropzone({ url: "/file/post" });

配置

有两种方式配置 dropzones.

一种就是和之前创建表单一样

另一种是通过js代码实现, 如下

lt;!DOCTYPE HTML>

<html>

<head>

<meta charset="utf-8">

<title>H5混合开发(runoob.com)</title>

<style type="text/css">

#div1{width:350px;height:70px;padding:10px;border:1pxsolid#aaaaaa;}

</style>

<script>

function allowDrop(ev)

{

ev.preventDefault();

}

function drag(ev)

{

ev.dataTransfer.setData("Text",ev.target.id);

}

function drop(ev)

{

ev.preventDefault();

var data=ev.dataTransfer.getData("Text");

ev.target.appendChild(document.getElementById(data));

}

</script>

</head>

<body>

<p>拖动 RUNOOB.COM 图片到矩形框中:</p>

<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>

<br>

<img id="drag1" src="img/logo.jpg" draggable="true" ondragstart="drag(event)" width="336" height="69">

</body>

</html>

它看上去也许有些复杂,不过我们可以分别研究拖放事件的不同部分。


设置元素为可拖放

首先,为了使元素可拖动,把 draggable 属性设置为 true :

<img draggable="true">


拖动什么 - ondragstart 和 setData()

然后,规定当元素被拖动时,会发生什么。

在上面的例子中,ondragstart 属性调用了一个函数,drag(event),它规定了被拖动的数据。

dataTransfer.setData() 方法设置被拖数据的数据类型和值:

function drag(ev)

{

ev.dataTransfer.setData("Text",ev.target.id);

}

在这个例子中,数据类型是 "Text",值是可拖动元素的 id ("drag1")。


放到何处 - ondragover

ondragover 事件规定在何处放置被拖动的数据。

默认地,无法将数据/元素放置到其他元素中。如果需要设置允许放置,我们必须阻止对元素的默认处理方式。

这要通过调用 ondragover 事件的 event.preventDefault() 方法:

event.preventDefault()


进行放置 - ondrop

当放置被拖数据时,会发生 drop 事件。

在上面的例子中,ondrop 属性调用了一个函数,drop(event):

function drop(ev)

{

ev.preventDefault();

var data=ev.dataTransfer.getData("Text");

ev.target.appendChild(document.getElementById(data));

}

代码解释:

  • 调用 preventDefault() 来避免浏览器对数据的默认处理(drop 事件的默认行为是以链接形式打开)

  • 通过 dataTransfer.getData("Text") 方法获得被拖的数据。该方法将返回在 setData() 方法中设置为相同类型的任何数据。

  • 被拖数据是被拖元素的 id ("drag1")

  • 把被拖元素追加到放置元素(目标元素)中

现目标:

  1. 可以一次选取多个图片上传;
  2. 上传的图片可以拖动排序;
  3. 点击图片提示删除弹窗,确认后删除该图片;
  4. 点击上传按钮图标,即可浏览图片,隐藏选择文件的文本框;
  5. 选择图片以后自动上传;
  6. 拖拽排序的时候使用transition-group,实现动画效果;

图1 多图上传效果


1、html代码

<tr class=''>
<td width="90" align="right">相关多图</td>
<td >
<div class='yllist yllist_x_duotu'>
<dl>
<!--存放上传的图片-->
<transition-group name="list">
<dd   v-for="(item,index) in listData " draggable="true" :key="item" 
	@click="del(index)" 
	@mouseover="showzz(1,index)"  
	@mouseleave="showzz(0,index)" 
	@dragstart="drag($event,index)" 
	@drop="drop($event,index)"
	@dragover='allowDrop($event)'
	>
    <img :src="item.picpath">
    <div class='zzz none'  :class="{'nonone':item.shs==1}">
    <div class='zzimg '><i class="fa fa-trash-o" aria-hidden="true"></i></div>
	</div>
</dd>
<!--结束-->
</transition-group>
<dd  @click="upbtn"  class='btnclass'><i class="fa fa-camera-retro" aria-hidden="true"></i>
<input type='file' id='multiple' accept="image/*"   multiple="multiple" style='display:none' @change="autoup"  name="ss">
</dd>
</dl>
<div class='clear'></div>
<div>
<span class='itemms'>说明:可以拖动改变顺序</span>
</div>
</div>
</td>
</tr>

说明:

@click="del(index)" 点击删除图片 index为数组的索引 点击的是第几个图片

@mouseover="showzz(1,index)" 鼠标放到上边 出现遮罩层 垃圾桶

@mouseleave="showzz(0,index)" 鼠标离开 遮罩层消失

@dragstart="drag($event,index)" 以下三个 用于拖拽排序

@drop="drop($event,index)"

@dragover='allowDrop($event)'

draggable="true" 设置为true 可以拖动

:key="item" 这里的key 要注意不能等于 index,要不然没有动画效果

img src的属性 是 :src="item.picpath" 不能是src={{item.picpath}}

<div class='zzz none' :class="{'nonone':item.shs==1}"> 设置遮罩层 shs=1的时候显示

上传的选择框设置为display:none隐藏

transition-group用法:

<transition-group name="list"> 实现拖拽的动画效果 后边的name可以随意写 ,但是要和css的.list-move {transition: transform 0.3s;} 【上边自定义的name,我这里是list】-move 设置该css 动画的时间

2、js代码

new Vue({
    el: '#app',
    data(){
		  tagslist:[
		    '网站开发',//存放的标签
			  '网站建设'
		  ],
		  tagsdt:"",  //绑定的标签文本框
		  tagindex:"",//删除标签的序号(索引)
		  listData: [
				  /*
			      {'picpath':'/public/upload/image/20211107/1.jpg',shs:0}
			      
				  shs   显示遮罩层 ,垃圾桶删除标志,0  不显示   1显示
				  */
		  ],
      file:"file",      //用于切换 file  text  实现同一个图片可以连续上传
		  tis:'',           //提示内容
		  showzzc:0,         //弹出框的显示,隐藏 。0 隐藏  1显示
		  showts:0,          //1 弹出提示操作框  2 弹出提示确认框 
		  lisindex:"",      //记录图片的索引
		  datameth:""       //根据这里的参数操作不同的方法
		 }
    },
    methods:{
	  tags:function(){
		  if(this.tagsdt){
		      this.tagslist.push(this.tagsdt); 
		  }
		  this.tagsdt="";
	  },
	  deltag:function(f){
		  this.showzzc=1;
		  this.showts=1;
		  this.tagindex=f;
		  this.datameth='tag';
	  },
	  hidetc:function(){
		  this.showzzc=0;
	  },
 	   del:function(key){
			this.showzzc=1;
			this.showts=1;
			this.lisindex=key;
			this.datameth="delpic";
			//this.listData.splice(key, 1);
		},
	  isdelc:function(){
			if(this.datameth=="delpic"){
		        this.listData.splice(this.lisindex, 1); 
			}
			if(this.datameth=="tag"){
		        this.tagslist.splice(this.tagindex, 1); 
			}
			this.showzzc=0;
	  }, 
  	showzz:function(meth,key){
			//console.log(this.listData[key].shs);
			if(!this.listData[key].shs){
			    this.$set(this.listData[key],'shs',0);
			}
			this.listData[key].shs=meth;
	  }, 
	  upbtn:function(){
		  document.getElementById("multiple").click();
	  },
	  autoup:function(){
		  let that=this;
      that.file="text";  //切换text  file
		  let ups=document.getElementById( "multiple");
		  let formdata=new FormData();
		  if(ups.files[0]){
			  if(ups.files.length>4){
				  this.showzzc=1;
				  this.showts=2;
				  this.tis="一次最多可以选择4张图片上传!";
          that.file="file";
				  return false;
			  }
        for(m=0;m<=ups.files.length-1;m++){
			      formdata.append("file", ups.files[m]);
			      axios.post("/api/uppic", formdata)
					  .then(function (response) {
					    if(response.data.error=='0000'){
							    that.listData.push(response.data.pic);
                  that.file="file";//重新切换为file
							  //console.log(JSON.stringify(that.listData));
						  }else{
							  that.showzzc=1;
							  that.showts=2;
							  that.tis=response.data.msg;
                that.file="file";
							  return false;
						  }
					  })
					  .catch(function (error) {
						  console.log(error);
					  });
          }
			    console.log(ups.outerHTML);
		  }  
    }
})

注意:上传图片以后一定要that.file="file",切换回file,不然会出现只能上传一次,下次选择当前图片不能上传的情况。

  1. 去掉js中的for循环和html的multiple="multiple"选择多个图片,就是单图的上传;
  2. 因为删除弹出提示的地方有2个,实际可能更多,在点击确认的时候不知道操作哪个删除,所以点删除图片或者是点删除信息标签的时候,向datameth赋不同的值,这样我们点击弹窗的确认,读取datameth的值,使用if判断,就可以知道要删除图片还是删除标签;
  3. 上传图片,删除图片用到的弹窗,在前边十七章有说明;

上边的上传是选取多个然后for循环逐个上传的,也可以file使用数组file[]批量提交,如下:

for(m=0;m<=ups.files.length-1;m++){
			      formdata.append("file[]", ups.files[m]);
}
axios.post("/api/uppic", formdata)

但是这样做的话,后台使用

foreach($_FILES as $k=>$v){
}

得到的$v['name']就是数组,需要我们再次for循环,得到单个的图片信息,返回以后的信息因为是数组,push只能一次追加一个,就只能再次循环,感觉很麻烦还不如开始就循环,一个一个的上传。

3、信息标签html

<tr class=''>
<td width="90" align="right">信息标签</td>
<td>
<div class="layui-input-inline tagslist" >
    <span class='tagspan' v-for="(tag,key) in tagslist"   :key="key" @click="deltag(key)">{{tag}}</span>
</div>
<input type="text"  class='inpMain' id='tags' style='width:150px;'  @blur="tags" v-model="tagsdt" /> <span class='itemms'>点击标签可以删除</span>
 <span class='itemms'></span>
</td>
</tr>

输入文本框绑定tagsdt,当我们鼠标离开该文本框的时候,通过blur使用tags方法读取绑定的tagsdt,可以获得输入的内容,这里需要判断是否为空,如果不为空再push进数组:this.tagslist.push(this.tagsdt);

4、php后端代码

foreach($_FILES as $k=>$v){
       $v['name'],$v['size'],$v['tem_name']
  就是图片的基本信息,使用move_uploaded_file移动到指定文件夹
  			$imags['picpath']=$path;
				$imags['shs']=0;
}
exit(json_encode(array('error'=>'0000','pic'=>$imags),JSON_UNESCAPED_UNICODE));

move_uploaded_file用法:

当前文件:$v["tmp_name"],

目标文件:ROOT_PATH.$images_dir.$newname

move_uploaded_file($v["tmp_name"], ROOT_PATH.$images_dir.$newname);

再次强调上传图片,要验证图片的安全性,防止图片木马!