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

问题描述 投票:0回答:3

假设:可以访问 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);

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

javascript file drag-and-drop data-transfer data-transfer-objects
3个回答
6
投票

您可以使用@kol 在 Simulate drop file event

发布的方法

也就是说,我们必须向 ondrop 传递一个参数,这

  • 有一个
    dataTransfer
    字段和
    files
    数组子字段,其中包含选定的
    File
  • a
    preventDefault
    方法(没有主体的函数即可)。
下面进行了调整,以在

.addEventListener("drop")

 事件中将 
drop
 附加到 
dragstart
 元素,将 
File
 对象传递到带有 
Function.prototype.bind()
 的绑定函数,该函数返回上述适当的对象,并在第三个参数处传递 
once:true
 
.addEventListener()
,对于访问或创建 
drop
 对象的每个 
dragstart
 事件最多调用一次 
File
 事件。

FileList

对象是只读的,Array
用于将
File
对象存储在事件处理程序中普通
dataTransfer.files
对象内的
javascript
属性中。

注意:

FileList

 接口应被视为“有风险”
  因为Web平台的大趋势是取代这样的
  与 ECMAScript 中的 Array
 平台对象接口
[ECMA-262]。特别是,这意味着排序的语法 filelist.item(0)
 处于危险之中;大多数其他编程用途
  
FileList
 不太可能受到最终迁移到
  
Array
类型。

如果

event.dataTransfer.files

 事件中的 
dragstart
 包含 
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


6
投票
最简单的方法是“添加项目”:

const dataTransfer = new DataTransfer(); const aFileParts = ['<a id="a"><b id="b">hey!</b></a>']; dataTransfer.items.add(new File([new Blob(aFileParts, { type: 'text/html' })], 'test.txt'));
只有您需要的是将文件调整为文件类型:)


0
投票
您无法将文件添加到 Chromium 上的

DataTransferItemList

。它甚至不被视为错误。非常狡猾。 
https://issues.chromium.org/issues/40853586

<html> <body> <div draggable="true" id="x" style="width:100px;height:100px;background:black;color:white">DRAG THIS</div> <script> const x = document.getElementById('x'); x.addEventListener('dragstart', e => { const i = e.dataTransfer.items.add(new File(['hello'], 'hello.txt', { type: 'text/plain' })); console.log(`[dragstart] Added ${i.kind} of type ${i.type}`); }); document.addEventListener('dragover', e => { e.preventDefault(); }); document.addEventListener('drop', e => { e.preventDefault(); for (const item of e.dataTransfer.items) { const f = item.getAsFile(); if (f) { console.log(`[drop] Received file of type ${item.type}`); } else { item.getAsString(data => { console.log(`[drop] Received string: ${data}`); }); } } }) </script> </body> </html>

© www.soinside.com 2019 - 2024. All rights reserved.