File drag and drop

HTML拖放接口使得web应用能够在网页中拖放文件。这篇文档介绍了web应用如何接受从底层平台的文件管理器拖动一个或多个文件到网页的操作。

拖放的主要步骤是为 drop 事件定义一个释放区(释放文件的目标元素)和为dragover事件定义一个事件处理程序。下面描述了这些步骤,包括示例程序片段。完整的源码在MDN's drag-and-drop repository (欢迎提交pull requests和/或issues).

注意: HTML drag and drop定义了两套不同的API来支持拖放文件。一个DataTransfer接口和另一个DataTransferItemDataTransferItemList接口。这个示例介绍了这两种API的用法(没有使用任何Gecko专用的接口)。

定义拖放区域

触发 drop 事件的目标元素需要一个ondrop 事件处理函数 。下面这一段代码以一个 <div> 元素为例展示了这些工作是如何完成的:

<div id="drop_zone" ondrop="dropHandler(event);">
  <p>Drag one or more files to this Drop Zone ...</p>
</div>

一般来说,在实际应用中需要定义一个 dragover 事件的处理函数并在其中加入关闭浏览器默认拖放行为的代码。你需要定义一个 ondragover 事件处理函数:

<div id="drop_zone" ondrop="dropHandler(event);" ondragover="dragOverHandler(event);">
  <p>Drag one or more files to this Drop Zone ...</p>
</div>

最后,在实际应用中可能需要给实现释放文件的元素加些样式来从视觉上向使用者说明这是一个有效释放区域。在这个示例中,实现释放文件的元素将使用如下样式:

#drop_zone {
  border: 5px solid blue;
  width:  200px;
  height: 100px;
}

注意当执行将文件拖入浏览器的操作时操作系统并不会触发 dragstart 和 dragend 事件。

执行释放事件

当用户释放文件时 drop 事件将会被触发。在下面的 drop 处理函数中,如果浏览器支持 DataTransferItemList 接口,则可以使用 getAsFile() 来获取每个文件;否则使用 DataTransfer 接口的 files 属性来获取每个文件。

这个示例展示了如何讲每个被拖动的文件的名字输出到控制台。在实际应用中可能会用到 File API 来处理一个文件。

注意在这个例子中,任何被拖动的非文件内容都会被忽略。

function dropHandler(ev) {
  console.log('File(s) dropped');

  // Prevent default behavior (Prevent file from being opened)
  ev.preventDefault();

  if (ev.dataTransfer.items) {
    // Use DataTransferItemList interface to access the file(s)
    for (var i = 0; i < ev.dataTransfer.items.length; i++) {
      // If dropped items aren't files, reject them
      if (ev.dataTransfer.items[i].kind === 'file') {
        var file = ev.dataTransfer.items[i].getAsFile();
        console.log('... file[' + i + '].name = ' + file.name);
      }
    }
  } else {
    // Use DataTransfer interface to access the file(s)
    for (var i = 0; i < ev.dataTransfer.files.length; i++) {
      console.log('... file[' + i + '].name = ' + ev.dataTransfer.files[i].name);
    }
  }
}

阻止浏览器的默认释放行为

下面的 dragover 事件处理函数调用  preventDefault() 来关闭浏览器的默认拖动和释放行为。

function dragOverHandler(ev) {
  console.log('File(s) in drop zone'); 

  // Prevent default behavior (Prevent file from being opened)
  ev.preventDefault();
}

参见