javascript - 如何使用 Javascript 将文件添加到现有的 dataTransfer 对象中

标签 javascript file drag-and-drop data-transfer data-transfer-objects

假设:一个可以访问 file://的本地 HTML/Javascript 网页

在可拖动的 HTML 元素上开始拖动时,在事件处理函数 dragStart(e) 中,我如何添加一个 File 对象,以便它被识别为一个文件并结束在 dataTransfer.files 列表中?

例如:

function dragStart(e){
    var file = getSomeFileObjFromSomewhere();
    e.originalEvent.dataTransfer.effectAllowed = "all";
    e.originalEvent.dataTransfer.setData("file", file);

    console.log("\nFiles:");
    i = 0;
    var files = e.originalEvent.dataTransfer.files,
    len = files.length;
    for (; i < len; i++) {
        console.log("\nIndex: " + i + "\nFilename: " + files[i].name);
        console.log("Type: " + files[i].type);
        console.log("Size: " + files[i].size + " bytes");
        console.dir(files[i]);
    }
}

具体来说,它需要在 Chrome/Chromium 上运行。并且,我们可以假设该文件存在于本地驱动器上。基本上,当将文件从 Windows 资源管理器拖动到可放置元素上的 HTML 页面时,我希望获得相同的数据。

我知道这存在于 Chrome 中:

e.originalEvent.dataTransfer.setData("DownloadURL", fileType + ":" + name + ":" + filePath);

下载文件。但这不是我想要的,因为我想假设这是一个现有文件并且必须访问原始文件。

最佳答案

您可以使用@kol 在 Simulate drop file event 发布的方法

That is, we have to pass an argument to ondrop, which

  • has a dataTransfer field with a files array subfield, which contains the selected File, and
  • a preventDefault method (a function with no body will do).

调整如下附.addEventListener("drop")drop元素位于 dragstart事件,与 File使用 Function.prototype.bind() 传递给绑定(bind)函数的对象它返回上述适当的对象,带有 once:true在第三个参数传递给 .addEventListener() , 调用 drop每个事件最多一次 dragstart事件地点 File访问或创建对象。

FileList 对象是只读的,一个 Array用于存储File对象在 dataTransfer.files平原内的属性(property)javascript事件处理程序中的对象。

Note: The FileList interface should be considered "at risk" since the general trend on the Web Platform is to replace such interfaces with the Array platform object in ECMAScript [ECMA-262]. In particular, this means syntax of the sort filelist.item(0) is at risk; most other programmatic use of FileList is unlikely to be affected by the eventual migration to an Array type.

如果event.dataTransfer.filesdragstart事件包含 File对象,迭代 FileList并推送每个 File反对 files数组。

var drag = document.getElementById("drag")
var drop = document.getElementById("drop")

function handleDrop(evt) {
  evt.preventDefault();
  console.log(evt.dataTransfer.files);
}

function getSomeFileObjFromSomewhere() {
  var data = ["abc", "def"];
  var files = [];
  for (var i = 0; i < data.length; i++) {
    files.push(new File([data[i]], data[i] + ".text", {
      type: "text/plain",
      lastModified: new Date().getTime()
    }));
  }
  return files
}

function dataTransferFileObject(files) {
  return {
    preventDefault: function() {},
    dataTransfer: {
      files: Array.isArray(files) ? files : [files]
    }
  }
}

drag.addEventListener("dragstart", function dragStart(e) {

  var files = getSomeFileObjFromSomewhere();
  e.dataTransfer.effectAllowed = "all";

  console.log("\nFiles:");
  
  for (let i = 0; i < files.length; i++) {
    var {name, size, type} = files[i];
    console.log("\nFilename: " + name);
    console.log("Type: " + type);
    console.log("Size: " + size + " bytes");
  }
  // if `e.dataTransfer.files`, push `File` objects dragged
  // to `files` array
  if (e.dataTransfer.files) {
    for (let file of e.dataTransfer.files) {
      files.push(file);
    }
  }
  
  drop.addEventListener("drop"
  , handleDrop.bind(drop, dataTransferFileObject(files))
  , {once: true});

});

drop.addEventListener("dragover", function(evt) {
  evt.preventDefault()
});
div {
  width: 50px;
  height: 50px;
  padding: 10px;
  margin: 10px;
}

div:nth-child(1) {
  border: 2px dotted blue;
}

div:nth-child(2) {
  border: 2px dotted green;
}
<div draggable="true" id="drag">drag</div>
<div droppable="true" id="drop" webkitdropzone="webkitdropzone">drop</div>

plnkr http://plnkr.co/edit/ihQqs4t2zOg2XhIuNwal?p=preview

关于javascript - 如何使用 Javascript 将文件添加到现有的 dataTransfer 对象中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24496989/

相关文章:

javascript - 拖放后保存HTML5 Canvas 的状态等

drag-and-drop - 有没有办法对dropzone.js实例中的预览元素进行拖放重新排序?

javascript - Uncaught Error : [$injector:modulerr] Failed to instantiate module myApp due to: Error: [$injector:unpr] Unknown provider: $routeProvider

javascript - 通过 javascript 调整 SVG viewBox 行为

java - 有没有办法让需要文件参数的命令行程序使用标准输入?

javascript - 在 Google Chrome 中创建的 Blob 文件可以存在多久?

javascript - MD-chips 电子邮件验证

javascript - 更改 dateRangePicker 的日期格式

java - 如何将 jtextfield 值作为日志保存到 .txt 文件?

JQuery UI 停止激活两次