阻止浏览器加载拖放文件

Tra*_*vis 174 javascript jquery html5 drag-and-drop

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

当文件被放入上传区域时,一切都很好.

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

我该如何防止这种行为?

谢谢!

Dig*_*ane 272

您可以向窗口添加事件侦听器,以调用preventDefault()所有dragover和drop事件.
例:

window.addEventListener("dragover",function(e){
  e = e || event;
  e.preventDefault();
},false);
window.addEventListener("drop",function(e){
  e = e || event;
  e.preventDefault();
},false);
Run Code Online (Sandbox Code Playgroud)

  • dragover是我失踪的那件作品. (35认同)
  • 注意:这也禁止将文件拖到`<input type ="file"/>`上.有必要检查`e.target`是否是文件输入并让这些事件通过. (13认同)
  • 我确认需要'dragover`和`drop`处理程序来阻止浏览器加载被删除的文件.(Chrome最新2015/08/03).该解决方案也适用于FF最新版本. (8认同)
  • 什么 ?窗口dragover为什么要加载文件?这毫无意义...... (5认同)
  • 这非常有效,我可以确认它可以与配置为接受拖放事件的页面元素结合使用,例如来自resumable.js等拖放文件上载程序的页面元素.在用户意外删除他们想要在实际文件上传放置区域之外上传的文件的情况下,防止默认浏览器行为很有用,然后想知道为什么他们现在看到直接在浏览器窗口中呈现的同一文件(假设一个兼容的文件类型,如图像或视频被删除),而不是看到他们的文件上传的预期行为. (4认同)
  • 您必须添加 e.dataTransfer.dropEffect = "none"; 以防止视觉反馈。 (3认同)
  • 是否也可以不显示移动/复制图标? (2认同)

Axe*_*hor 33

经过大量的摆弄,我发现这是最安全的解决方案:

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";
  }
});
Run Code Online (Sandbox Code Playgroud)
<div id="dropzone">...</div>
Run Code Online (Sandbox Code Playgroud)

无论是否设置了新属性,在窗口上设置effectAllowdropEffect无条件都会导致我的放置区不再接受任何dnd.


ent*_*ast 8

要允许只对某些元素进行拖放,您可以执行以下操作:

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);
Run Code Online (Sandbox Code Playgroud)


Vis*_*ioN 8

对于jQuery,正确的答案是:

$(document).on({
    dragover: function() {
        return false;
    },
    drop: function() {
        return false;
    }
});
Run Code Online (Sandbox Code Playgroud)

这里的return false行为event.preventDefault()event.stopPropagation().


Sup*_*ole 5

注意:虽然 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';
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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