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专用的接口)。

Define the drop zone

The target element of the drop event needs an ondrop global event handler. The following code snippet shows how this is done with a <div> element:

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

Typically, an application will include a dragover event handler on the drop target element and that handler will turn off the browser's default drag behavior. To add this handler, you need to include a ondragover global event handler:

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

Lastly, an application may want to style the drop target element to visually indicate the element is a drop zone. In this example, the drop target element uses the following styling:

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

Note that dragstart and dragend events are not fired when dragging a file into the browser from the OS.

Process the drop

The drop event is fired when the user drops the file(s). In the following drop handler, if the browser supports DataTransferItemList interface, the getAsFile() method is used to access each file; otherwise the DataTransfer interface's files property is used to access each file.

This example shows how to write the name of each dragged file to the console. In a real application, an application may want to process a file using  the File API.

Note that in this example, any drag item that is not a file is ignored.

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);
    }
  }
}

Prevent the browser's default drag behavior

The following dragover event handler calls preventDefault() to turn off the browser's default drag and drop handler.

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

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

See also