防止浏览器加载拖放文件

IT技术 javascript jquery html drag-and-drop
2021-03-02 04:15:59

我正在向我的页面添加一个 html5 拖放上传器。

当文件被放入上传区域时,一切正常。

但是,如果我不小心将文件放到了上传区域之外,浏览器就会像加载新页面一样加载本地文件。

我怎样才能防止这种行为?

谢谢!

6个回答

您可以向调用preventDefault()所有拖放事件的窗口添加事件侦听器
例子:

window.addEventListener("dragover",function(e){
  e = e || event;
  e.preventDefault();
},false);
window.addEventListener("drop",function(e){
  e = e || event;
  e.preventDefault();
},false);
我确认需要dragoverdrop处理程序来防止浏览器加载删除的文件。(Chrome 最新版 2015/08/03)。该解决方案也适用于最新的 FF。
2021-04-16 04:15:59
Dragover 是我缺少的那一块。
2021-04-21 04:15:59
什么 ?为什么窗口拖放要加载文件?这毫无意义……
2021-04-26 04:15:59
这非常有效,我可以确认它可以与配置为接受放置事件的页面元素结合使用,例如来自拖放文件上传脚本(如 resumable.js)的元素。如果用户不小心将要上传的文件放置在实际文件上传放置区之外,然后想知道为什么他们现在会直接在浏览器窗口中看到相同的文件,则可以防止默认浏览器行为(假设删除了兼容的文件类型(如图像或视频),而不是看到其文件上传的预期行为。
2021-05-09 04:15:59
注意:这也会禁止将文件拖到<input type="file" />. 有必要检查是否e.target是文件输入并让此类事件通过。
2021-05-15 04:15:59

经过大量摆弄后,我发现这是最稳定的解决方案:

var dropzoneId = "dropzone";

window.addEventListener("dragenter", function(e) {
  if (e.target.id != dropzoneId) {
    e.preventDefault();
    e.dataTransfer.effectAllowed = "none";
    e.dataTransfer.dropEffect = "none";
  }
}, false);

window.addEventListener("dragover", function(e) {
  if (e.target.id != dropzoneId) {
    e.preventDefault();
    e.dataTransfer.effectAllowed = "none";
    e.dataTransfer.dropEffect = "none";
  }
});

window.addEventListener("drop", function(e) {
  if (e.target.id != dropzoneId) {
    e.preventDefault();
    e.dataTransfer.effectAllowed = "none";
    e.dataTransfer.dropEffect = "none";
  }
});
<div id="dropzone">...</div>

在窗口上同时设置effectAllowdropEffect无条件设置会导致我的拖放区不再接受任何 dnd,无论属性是否设置为新的。

e.dataTransfer() 是这里使这项工作的关键部分,“接受的答案”没有提到。
2021-05-06 04:15:59
e.target.id您可以event.stopPropagation()从放置区的事件处理程序调用而不是检查此外,没有必要effectedAlled像@HoldOffHunger 提到的那样在这里设置
2021-05-10 04:15:59

对于 jQuery,正确答案是:

$(document).on({
    dragover: function() {
        return false;
    },
    drop: function() {
        return false;
    }
});

这里return false将表现为event.preventDefault()event.stopPropagation()

要仅允许在某些元素上拖放,您可以执行以下操作:

window.addEventListener("dragover",function(e){
  e = e || event;
  console.log(e);
  if (e.target.tagName != "INPUT") { // check which element is our target
    e.preventDefault();
  }
},false);
window.addEventListener("drop",function(e){
  e = e || event;
  console.log(e);
  if (e.target.tagName != "INPUT") {  // check which element is our target
    e.preventDefault();
  }  
},false);
对我来说很完美,但我也会添加对 type=file 的检查,否则你仍然可以拖动到文本输入
2021-04-24 04:15:59

注意:虽然 OP 没有要求提供 Angular 解决方案,但我是来这里寻找的。所以这是分享我发现的一个可行的解决方案,如果你使用 Angular。

根据我的经验,当您向页面添加文件放置功能时,首先会出现此问题。因此,我的观点是,添加此内容的组件也应该负责防止放置在放置区之外。

在我的解决方案中,拖放区是一个带有类的输入,但任何明确的选择器都可以工作。

import { Component, HostListener } from '@angular/core';
//...

@Component({
  template: `
    <form>
      <!-- ... -->
      <input type="file" class="dropzone" />
    </form>
  `
})
export class MyComponentWithDropTarget {

  //...

  @HostListener('document:dragover', ['$event'])
  @HostListener('drop', ['$event'])
  onDragDropFileVerifyZone(event) {
    if (event.target.matches('input.dropzone')) {
      // In drop zone. I don't want listeners later in event-chain to meddle in here
      event.stopPropagation();
    } else {
      // Outside of drop zone! Prevent default action, and do not show copy/move icon
      event.preventDefault();
      event.dataTransfer.effectAllowed = 'none';
      event.dataTransfer.dropEffect = 'none';
    }
  }
}

创建/销毁组件时会自动添加/删除侦听器,并且由于stopPropagation(),同一页面上使用相同策略的其他组件不会相互干扰。

这就像一个魅力!浏览器甚至通过添加一个非常棒的禁止图标来改变鼠标光标!
2021-04-26 04:15:59
Therefore my opinion is that the component that adds this, should also be responsible for preventing drop outside of the drop zone.“说得好!
2021-05-15 04:15:59