js控制文件拖拽,从粘贴板获取图片,接入angularjs
1、本文主要实现的功能是文件拖拽到指定标签区域能后获取到相关事件和文件
2、从粘贴板获取到图片信息(主要目的就是实现网页聊天功能能够拖拽发送文件,粘贴发送图片功能)
拖拽事件
js
能够监听到拖拽的事件有drag
、dragend
、dragenter
、dragexit(没有浏览器实现)
、dragleave
、dragover
、dragstart
、drop
,详细的内容可以看MDN。
其中,与拖拽文件相关的事件有dragenter(文件拖拽进)
、dragover(文件拖拽在悬浮)
、dragleave(文件拖拽离开)
、drop(文件拖拽放下)
。
拖拽事件可以绑定到指定的DOM元素上,可以绑定到整个页面中。
var dropEle = document.querySelector('#dropZone');dropEle.addEventListener('drop', function (e) { // }, false);
阻止默认行为
一般来说,我们只要要把解决拖拽文件的业务逻辑写到drop事件中即可以了,为什么还要绑定dragenter
、dragover
、dragleave
这三个事件呢?
由于当你拖拽一个文件到没有对拖拽事件进行解决的浏览器中的时候,浏览器会打开这个文件,比方拖拽一张图片浏览器会打开这个图片,在没有PDF阅读器的时候也可以拖拽一个PDF到浏览器中,浏览器就会打开这个PDF文件。
假如浏览器打开了拖拽的文件,页面就跳走了,我们希望得到拖拽的文件,而不是让页面跳走。上面说到浏览器会打开拖拽的文件是浏览器的默认行为,我们需要阻止这个默认行为,就需要再上述的事件中进行阻止。
假如你只使用了drop
事件,需要再加入以下一个或者者多个事件,防止浏览器默认打开
dropZone.addEventListener("dragenter", function (e) { e.preventDefault(); e.stopPropagation();}, false);dropZone.addEventListener("dragover", function (e) { e.preventDefault(); e.stopPropagation();}, false);dropZone.addEventListener("dragleave", function (e) { e.preventDefault(); e.stopPropagation();}, false);dropZone.addEventListener("drop", function (e) { e.preventDefault(); e.stopPropagation(); // 解决拖拽文件的逻辑}
实际上dragenter
不阻止默认行为也不会触发浏览器打开文件,为了防止某些浏览器可能有的兼容性问题,把拖拽周期中的所有的事件都阻止默认行为并且阻止了事件冒泡。
在我实际测试的时候 将文件拖入到可编辑区域的时候 drop
是没问题,浏览器不会执行浏览器的默认程序,非编辑状态的标签是会打开的。
取得拖拽的文件
我们会在drop
这个事件的回调中的事件对象能够得到文件对象。
在事件对象中,一个e.dataTransfer
这样的属性,它是一个DataTransfer类型的数据,有如下的属性
属性 | 类型 | 说明 |
---|---|---|
dropEffect | String | 用来hack某些兼容性问题 |
effectAllowed | String | 暂时不用 |
files | FileList | 拖拽的文件列表 |
items | DataTransferItemList | 拖拽的数据(有可能是字符串) |
types | Array | 拖拽的数据类型 该属性在Safari下比较混乱 |
在Chrome中我们用items
对象取得文件,其余浏览器用files
取得文件,主要是为了解决拖拽文件夹的问题,最好不允许客户拖拽文件夹,由于文件夹内可能还有文件夹,递归上传文件会很久,假如不递归查找,只上传目录第一层级的文件,客户可能以为上传功能了,但是没有上传子目录文件,所以还是禁止上传文件夹比较好,后面我会说要怎样解决。
测试代码
<!DOCTYPE html><html><head> <title>drap</title></head><script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script><body> <div id="dropZone" style="width: 500px;height: 500px;background-color: red"> </div></body><script type="text/javascript"> var dropEle = document.querySelector("#dropZone"); dropEle.addEventListener("dragenter", function (e) { e.preventDefault(); e.stopPropagation(); console.log('dragenter') }, false); dropEle.addEventListener("dragover", function (e) { e.preventDefault(); e.stopPropagation(); console.log('dragover') }, false); dropEle.addEventListener("dragleave", function (e) { e.preventDefault(); e.stopPropagation(); console.log('dragleave') }, false); dropEle.addEventListener("drop", function (e) { e.preventDefault(); e.stopPropagation(); var df = e.dataTransfer; var dropFiles = []; // 存放拖拽的文件对象 if(df.items !== undefined) { // Chrome有items属性,对Chrome的单独解决 for(var i = 0; i < df.items.length; i++) { var item = df.items[i]; // 用webkitGetAsEntry禁止上传目录 if(item.kind === "file" && item.webkitGetAsEntry().isFile) { var file = item.getAsFile(); dropFiles.push(file); console.log("------") console.log(file); console.log(df.files[0]); } } }else{ for(var i = 0; i < df.files.length; i++) { if ( dropFile.type ) { // 假如type不是空串,肯定是文件 dropFiles.push(dropFile); console.log(dropFile) } else { try { var fileReader = new FileReader(); fileReader.readAsDataURL(dropFile.slice(0, 3)); fileReader.addEventListener('load', function (e) { console.log(e, 'load'); dropFiles.push(dropFile); }, false); fileReader.addEventListener('error', function (e) { console.log(e, 'error,不可以上传文件夹'); }, false); } catch (e) { console.log(e, 'catch error,不可以上传文件夹'); } } } } }, false);</script></html>
接入到angularjs 中, 功能比较独立所以就把他写成指令
.directive('dropFile',['$log','Tools',function($log,Tools){ return{ restrict:'A', link:function (scope,element,attrs) { //为了防止浏览器默认打开文件 angular.element(element).on("dragover",function (e) { e.preventDefault(); }); angular.element(element).on("drop", function (e) { scope.imgs=[]; scope.files=[]; e.preventDefault(); e.stopPropagation(); var df = e.originalEvent.dataTransfer;//这个地方和javascript 有些不一样需要注意否则取不到值 var dropFiles = []; // 存放拖拽的文件对象 if (df.items !== undefined) { // Chrome有items属性,对Chrome的单独解决 for (var i = 0; i < df.items.length; i++) { var item = df.items[i]; // 用webkitGetAsEntry禁止上传目录 if (item.kind === "file" && item.webkitGetAsEntry().isFile) { var file = item.getAsFile(); dropFiles.push(file); } } } else { for (var i = 0; i < df.files.length; i++) { if (dropFile.type) { // 假如type不是空串,肯定是文件 dropFiles.push(dropFile); } else { try { var fileReader = new FileReader(); fileReader.readAsDataURL(dropFile.slice(0, 3)); fileReader.addEventListener('load', function (e) { console.log(e, 'load'); dropFiles.push(dropFile); }, false); fileReader.addEventListener('error', function (e) { console.log(e, 'error,不可以上传文件夹'); }, false); } catch (e) { console.log(e, 'catch error,不可以上传文件夹'); } } } } //拿到文件去做相关业务操做 if(dropFiles.length>0){ var data = {}; data["files"] = dropFiles; scope.$broadcast("$$dropFile",data); } }); } } }]);
从粘贴版获取图片
需要标签监听paste
事件、angularjs
中有ng-paste
事件监听,我们直接使用就可
$scope.copyFile=function (event) { if ( event.clipboardData || event.originalEvent ) { //not for ie11 某些chrome版本使用的是event.originalEvent var clipboardData = (event.clipboardData || event.originalEvent.clipboardData); if ( clipboardData.items ) { // for chrome var items = clipboardData.items, len = items.length, blob = null; //在items里找粘贴的image,据上面分析,需要循环 for (var i = 0; i < len; i++) { if (items[i].type.indexOf("image") !== -1) { //getAsFile() 此方法只是living standard firefox ie11 并不支持 blob = items[i].getAsFile(); var data = {}; var files = []; files.push(blob); //业务逻辑 data["files"] = files; $scope.$broadcast("$$dropFile",data); event.stopPropagation(); event.preventDefault(); } } } else { //for firefox $log.log("您的浏览器不支持功能"); } } }
参考博客
- js控制文件拖拽,获取拖拽内容。
- js实现ctrl+v粘贴上传图片(兼容chrome、firefox、ie11)
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » js控制文件拖拽,从粘贴板获取图片,接入angularjs