search
HomeWeb Front-endJS Tutorialjs controls file dragging and obtains dragging content

js controls file dragging and obtains dragging content

Feb 23, 2018 pm 02:52 PM
javascriptcontentObtain

When the user drags a file to an element in the browser, js can monitor the events related to dragging and process the dragging results. This article discusses some issues related to dragging files. problem, but did not deal with too many issues regarding compatibility.

Drag events

<span style="font-size: 14px;">js</span>The events that can be monitored for drag and drop are<span style="font-size: 14px;">drag</span>#、<span style="font-size: 14px;">dragend</span><span style="font-size: 14px;">dragenter</span><span style="font-size: 14px;">dragexit(no browser implementation)</span><span style="font-size: 14px;">dragleave</span> <span style="font-size: 14px;">dragover</span><span style="font-size: 14px;">dragstart</span> <span style="font-size: 14px;">drop</span>, please see MDN for details.

Among them, the events related to dragging files include <span style="font-size: 14px;">dragenter(file dragging in)</span>, <span style="font-size: 14px;">dragover(The file is dragged and dropped)</span><span style="font-size: 14px;">dragleave(The file is dragged and dropped)</span> ,<span style="font-size: 14px;">drop(drag and drop the file)</span>.
Drag events can be bound to specified DOM elements or to the entire page.

<span style="font-size: 14px;">var dropEle = document.querySelector('#dropZone');<br>dropEle.addEventListener('drop', function (e) {<br>    // <br>}, false);<br><br>document.addEventListener('drop', function (e) {<br>    // <br>}, false);<br></span>

Prevent default behavior

Generally speaking, we only need to write the business logic for handling drag and drop files<span style="font-size: 14px;">drop</span> can be done in the event, why do we need to bind <span style="font-size: 14px;">dragenter</span><span style="font-size: 14px;">dragover</span><span style="font-size: 14px;">dragleave</span>What about these three events?

Because when you drag a file to a browser that does not handle the drag event, the browser will open the file. For example, if you drag a picture, the browser will Open this image and drag a PDF to the browser without a PDF reader, and the browser will open the PDF file.

If the browser opens the dragged file, the page will jump away. We hope to get the dragged file instead of letting the page jump away. As mentioned above, it is the default behavior of the browser to open the dragged file. If we need to prevent this default behavior, we need to prevent it in the above event.

<span style="font-size: 14px;">dropZone.addEventListener("dragenter", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br>}, false);<br><br>dropZone.addEventListener("dragover", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br>}, false);<br><br>dropZone.addEventListener("dragleave", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br>}, false);<br><br>dropZone.addEventListener("drop", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br>    // 处理拖拽文件的逻辑<br>}<br></span>

Actually<span style="font-size: 14px;">dragenter</span> does not block the default behavior and does not trigger the browser to open the file. In order to prevent certain Some browsers may have compatibility issues that prevent all events in the drag cycle from default behavior and prevent event bubbling.

Get the dragged file

We will drop it in<span style="font-size: 14px;"></span>The event object in the callback of this event can get the file object.

In the event object, a property like <span style="font-size: 14px;">e.dataTransfer</span> is a <span style="font-size: 14px;">DataTransfer</span> type of data has the following attributes

Attribute Type Description
<span style="font-size: 14px;">dropEffect</span> String Used to hack some compatibility issues
effectAllowed String Not used for the time being
<span style="font-size: 14px;">files</span> FileList Drag and drop file list
<span style="font-size: 14px;">items</span> DataTransferItemList Drag data (may be a string)
types Array The dragging data type should be Properties are confusing in Safari

<span style="font-size: 14px;">Chrome</span>中我们用<span style="font-size: 14px;">items</span>对象获得文件,其他浏览器用<span style="font-size: 14px;">files</span>获得文件,主要是为了处理拖拽文件夹的问题,最好不允许用户拖拽文件夹,因为文件夹内可能还有文件夹,递归上传文件会很久,如果不递归查找,只上传目录第一层级的文件,用户可能以为上传功能了,但是没有上传子目录文件,所以还是禁止上传文件夹比较好,后面我会说要怎么处理。

Chrome获取文件

<span style="font-size: 14px;">dropZone.addEventListener("drop", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br>    <br>    var df = e.dataTransfer;<br>    var dropFiles = []; // 存放拖拽的文件对象<br>    <br>    if(df.items !== undefined) {<br>        // Chrome有items属性,对Chrome的单独处理<br>        for(var i = 0; i             var item = df.items[i];<br>            // 用webkitGetAsEntry禁止上传目录<br>            if(item.kind === "file" && item.webkitGetAsEntry().isFile) {<br>                var file = item.getAsFile();<br>                dropFiles.push(file);<br>            }<br>        }<br>    }<br>}<br></span>

其他浏览器获取文件

这里只测试了Safari,其他浏览器并没有测试,不过看完本文一定也有思路处理其他浏览器的兼容情况。

<span style="font-size: 14px;">dropZone.addEventListener("drop", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br>    <br>    var df = e.dataTransfer;<br>    var dropFiles = []; // 存放拖拽的文件对象<br>    <br>    if(df.items !== undefined) {<br>        // Chrome拖拽文件逻辑<br>    } else {<br>        for(var i = 0; i             dropFiles.push(df.files[i]);<br>        }<br>    }<br>}<br></span>

由于<span style="font-size: 14px;">Safari</span>没有<span style="font-size: 14px;">item</span>,自然也没有<span style="font-size: 14px;">webkitGetAsEntry</span>,所以在Safari无法确定拖拽的是否是文件还是文件夹。

非Chrome内核浏览器判断目录的方法

浏览器获取到的每个file对象有四个属性:<span style="font-size: 14px;">lastModified</span><span style="font-size: 14px;">name</span><span style="font-size: 14px;">size</span><span style="font-size: 14px;">type</span>,其中<span style="font-size: 14px;">type</span>是文件的<span style="font-size: 14px;">MIME Type</span>,文件夹的<span style="font-size: 14px;">type</span>是空的,但是有些文件没有<span style="font-size: 14px;">MIME Type</span>,如果按照<span style="font-size: 14px;">type</span>是否为空判断是不是拖拽的文件夹的话,会误伤一部分文件,所以这个方法行。

那么还有什么方法可以判断呢,思路大概是这样子的,用户拖拽的文件和文件夹应该是不一样的东西,用<span style="font-size: 14px;">File API</span>操作的时候应该会有区别,比如进行某些操作的时候,文件就能够正常操作,但是文件夹就会报错,通过错误的捕获就能够判断是文件还是文件夹了,好我们根据这个思路来写一下。

<span style="font-size: 14px;">dropZone.addEventListener("drop", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br><br>    var df = e.dataTransfer;<br>    var dropFiles = [];<br>    <br>    if(df.items !== undefined){<br>        // Chrome拖拽文件逻辑<br>    } else {<br>        for(var i = 0; i             var dropFile = df.files[i];<br>            if ( dropFile.type ) {<br>                // 如果type不是空串,一定是文件<br>                dropFiles.push(dropFile);<br>            } else {<br>                try {<br>                    var fileReader = new FileReader();<br>                    fileReader.readAsDataURL(dropFile.slice(0, 3));<br><br>                    fileReader.addEventListener('load', function (e) {<br>                        console.log(e, 'load');<br>                        dropFiles.push(dropFile);<br>                    }, false);<br><br>                    fileReader.addEventListener('error', function (e) {<br>                        console.log(e, 'error,不可以上传文件夹');<br>                    }, false);<br><br>                } catch (e) {<br>                    console.log(e, 'catch error,不可以上传文件夹');<br>                }<br>            }<br>        }<br>    }<br>}, false);<br></span>

上面代码创建了一个<span style="font-size: 14px;">FileReader</span>实例,通过这个实例对文件进行读取,我测试读取一个1G多的文件要3S多,时间有点长,就用<span style="font-size: 14px;">slice</span>截取了前3个字符,为什么是前3个不是前2个或者前4个呢,因为代码是我写的,我开心这么写呗~

如果<span style="font-size: 14px;">load</span>事件触发了,就说明拖拽过来的东西是文件,如果<span style="font-size: 14px;">error</span>事件触发了,就说明是文件夹,为了防止其他可能的潜在错误,用<span style="font-size: 14px;">try</span>包起来这段代码。

三方应用的一点点小hack

经过测试发现通过<span style="font-size: 14px;">Mac</span><span style="font-size: 14px;">Finder</span>拖拽文件没有问题,但是有时候文件并不一定在<span style="font-size: 14px;">Finder</span>中,也可能在某些应用中,有一个应用叫做<span style="font-size: 14px;">圈点</span>,这个应用的用户反馈文件拖拽失效,去看了其他开源文件上传的源码,发现了这样一行代码:

<span style="font-size: 14px;">dropZone.addEventListener("dragover", function (e) {<br>    e.dataTransfer.dropEffect = 'copy'; // 兼容某些三方应用,如圈点<br>    e.preventDefault();<br>    e.stopPropagation();<br>}, false);<br></span>

需要把<span style="font-size: 14px;">dropEffect</span>置为<span style="font-size: 14px;">copy</span>,上网搜了下这个问题,源码文档中也没有说为什么要加这个,有兴趣的同学可以找一下为什么。

可以拿来就用的代码

由于用了<span style="font-size: 14px;">FileReader</span>去读取文件,这是一个异步IO操作,为了记录当前处理了多少个文件,以及什么时候触发拖拽结束的回调,写了一个<span style="font-size: 14px;">checkDropFinish</span>的方法一直去比较处理的文件数量和文件总数,确定所有文件处理完了后就去调用完成的回调。

另外,我在最后调试异步处理的时候,用的断点调试,发现断点调试在<span style="font-size: 14px;">Safari</span>中会导致异步回调不触发,需要自己调试定制功能的同学注意下。

<span style="font-size: 14px;">// 获得拖拽文件的回调函数<br>function getDropFileCallBack (dropFiles) {<br>    console.log(dropFiles, dropFiles.length);<br>}<br><br>var dropZone = document.querySelector("#dropZone");<br>dropZone.addEventListener("dragenter", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br>}, false);<br><br>dropZone.addEventListener("dragover", function (e) {<br>    e.dataTransfer.dropEffect = 'copy'; // 兼容某些三方应用,如圈点<br>    e.preventDefault();<br>    e.stopPropagation();<br>}, false);<br><br>dropZone.addEventListener("dragleave", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br>}, false);<br><br>dropZone.addEventListener("drop", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br><br>    var df = e.dataTransfer;<br>    var dropFiles = []; // 拖拽的文件,会放到这里<br>    var dealFileCnt = 0; // 读取文件是个异步的过程,需要记录处理了多少个文件了<br>    var allFileLen = df.files.length; // 所有的文件的数量,给非Chrome浏览器使用的变量<br><br>    // 检测是否已经把所有的文件都遍历过了<br>    function checkDropFinish () {<br>        if ( dealFileCnt === allFileLen-1 ) {<br>            getDropFileCallBack(dropFiles);<br>        }<br>        dealFileCnt++;<br>    }<br><br>    if(df.items !== undefined){<br>        // Chrome拖拽文件逻辑<br>        for(var i = 0; i             var item = df.items[i];<br>            if(item.kind === "file" && item.webkitGetAsEntry().isFile) {<br>                var file = item.getAsFile();<br>                dropFiles.push(file);<br>                console.log(file);<br>            }<br>        }<br>    } else {<br>        // 非Chrome拖拽文件逻辑<br>        for(var i = 0; i             var dropFile = df.files[i];<br>            if ( dropFile.type ) {<br>                dropFiles.push(dropFile);<br>                checkDropFinish();<br>            } else {<br>                try {<br>                    var fileReader = new FileReader();<br>                    fileReader.readAsDataURL(dropFile.slice(0, 3));<br><br>                    fileReader.addEventListener('load', function (e) {<br>                        console.log(e, 'load');<br>                        dropFiles.push(dropFile);<br>                        checkDropFinish();<br>                    }, false);<br><br>                    fileReader.addEventListener('error', function (e) {<br>                        console.log(e, 'error,不可以上传文件夹');<br>                        checkDropFinish();<br>                    }, false);<br><br>                } catch (e) {<br>                    console.log(e, 'catch error,不可以上传文件夹');<br>                    checkDropFinish();<br>                }<br>            }<br>        }<br>    }<br>}, false);<br></span>

相关推荐:

如何实现文件拖拽上传

html5文件拖拽上传的示例代码分享

Dropzone.js实现文件拖拽上传功能

The above is the detailed content of js controls file dragging and obtains dragging content. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Javascript Data Types : Is there any difference between Browser and NodeJs?Javascript Data Types : Is there any difference between Browser and NodeJs?May 14, 2025 am 12:15 AM

JavaScript core data types are consistent in browsers and Node.js, but are handled differently from the extra types. 1) The global object is window in the browser and global in Node.js. 2) Node.js' unique Buffer object, used to process binary data. 3) There are also differences in performance and time processing, and the code needs to be adjusted according to the environment.

JavaScript Comments: A Guide to Using // and /* */JavaScript Comments: A Guide to Using // and /* */May 13, 2025 pm 03:49 PM

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python vs. JavaScript: A Comparative Analysis for DevelopersPython vs. JavaScript: A Comparative Analysis for DevelopersMay 09, 2025 am 12:22 AM

The main difference between Python and JavaScript is the type system and application scenarios. 1. Python uses dynamic types, suitable for scientific computing and data analysis. 2. JavaScript adopts weak types and is widely used in front-end and full-stack development. The two have their own advantages in asynchronous programming and performance optimization, and should be decided according to project requirements when choosing.

Python vs. JavaScript: Choosing the Right Tool for the JobPython vs. JavaScript: Choosing the Right Tool for the JobMay 08, 2025 am 12:10 AM

Whether to choose Python or JavaScript depends on the project type: 1) Choose Python for data science and automation tasks; 2) Choose JavaScript for front-end and full-stack development. Python is favored for its powerful library in data processing and automation, while JavaScript is indispensable for its advantages in web interaction and full-stack development.

Python and JavaScript: Understanding the Strengths of EachPython and JavaScript: Understanding the Strengths of EachMay 06, 2025 am 12:15 AM

Python and JavaScript each have their own advantages, and the choice depends on project needs and personal preferences. 1. Python is easy to learn, with concise syntax, suitable for data science and back-end development, but has a slow execution speed. 2. JavaScript is everywhere in front-end development and has strong asynchronous programming capabilities. Node.js makes it suitable for full-stack development, but the syntax may be complex and error-prone.

JavaScript's Core: Is It Built on C or C  ?JavaScript's Core: Is It Built on C or C ?May 05, 2025 am 12:07 AM

JavaScriptisnotbuiltonCorC ;it'saninterpretedlanguagethatrunsonenginesoftenwritteninC .1)JavaScriptwasdesignedasalightweight,interpretedlanguageforwebbrowsers.2)EnginesevolvedfromsimpleinterpreterstoJITcompilers,typicallyinC ,improvingperformance.

JavaScript Applications: From Front-End to Back-EndJavaScript Applications: From Front-End to Back-EndMay 04, 2025 am 12:12 AM

JavaScript can be used for front-end and back-end development. The front-end enhances the user experience through DOM operations, and the back-end handles server tasks through Node.js. 1. Front-end example: Change the content of the web page text. 2. Backend example: Create a Node.js server.

Python vs. JavaScript: Which Language Should You Learn?Python vs. JavaScript: Which Language Should You Learn?May 03, 2025 am 12:10 AM

Choosing Python or JavaScript should be based on career development, learning curve and ecosystem: 1) Career development: Python is suitable for data science and back-end development, while JavaScript is suitable for front-end and full-stack development. 2) Learning curve: Python syntax is concise and suitable for beginners; JavaScript syntax is flexible. 3) Ecosystem: Python has rich scientific computing libraries, and JavaScript has a powerful front-end framework.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

Powerful PHP integrated development environment

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),