如何使用 Javascript 将文件添加到已经存在的 dataTransfer 对象中
Posted
技术标签:
【中文标题】如何使用 Javascript 将文件添加到已经存在的 dataTransfer 对象中【英文标题】:How to add a file into an already existing dataTransfer object using Javascript 【发布时间】:2014-08-21 05:30:52 【问题描述】:假设:本地 html/javascript 网页可以访问 file://
在可拖动的 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);
下载文件。但这不是我想要的,因为我想假设这是一个现有文件并且必须访问原始文件。
【问题讨论】:
我怀疑这可以做到。如果我理解正确,您实际上是在要求浏览器上传某人的文件,而无需他们启动文件传输。我看不到允许这种情况发生的浏览器 - 这将是一个安全漏洞 如果您能够在var file = getSomeFileObjFromSomewhere();
获取文件,那么在event.dataTransfer
设置文件对象的目的是什么?你想达到什么目的?
@KScandrett - File 对象必须从 Javascript 已经可以访问的东西生成(包括通过用户与文件输入交互显式生成的 File 对象)
我正在尝试从一个页面生成一个文件,用户可以将其拖到另一个页面,就像他们将文件从文件系统拖到另一个页面一样
“另一页”是什么意思? Drag and drop images, and not links, between windows - HTML5?
【参考方案1】:
您可以使用@kol 在Simulate drop file event 发布的方法
也就是说,我们必须向 ondrop 传递一个参数,它
有一个dataTransfer
字段和一个files
数组子字段,其中包含选定的File
,并且preventDefault
方法(没有主体的函数可以)。
在下面进行了调整,以在 dragstart
事件处将 .addEventListener("drop")
附加到 drop
元素,将 File
对象传递给带有 Function.prototype.bind()
的绑定函数,该函数返回上述适当的对象,once:true
在第三个传递.addEventListener()
的参数,对于访问或创建 File
对象的每个 dragstart
事件最多调用一次 drop
事件。
FileList
对象是只读的,Array
用于将File
对象的dataTransfer.files
属性存储在事件处理程序的普通javascript
对象中。
注意:
FileList
接口应被视为“有风险” 因为网络平台上的大趋势是取代这样的 与 ECMAScript [ECMA-262] 中的Array
平台对象接口。特别是,这意味着排序的语法filelist.item(0)
有风险;大多数其他程序化使用FileList
不太可能受到最终迁移到Array
类型。
如果event.dataTransfer.files
at 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>
plnkrhttp://plnkr.co/edit/ihQqs4t2zOg2XhIuNwal?p=preview
【讨论】:
谢谢,这似乎是一个进步!从 dragstart 事件中查看时,它似乎可以工作,但 dataTransfer 项目/文件似乎不会持续到 drop 事件。还是我在那里做错了什么? plnkr.co/edit/H5gfm82JZGRuEuDIM7WM?p=preview @FabioBeltramini 注意,该问题实际上并未提及drop
事件。
好的,关于 drop 事件,也许我对这句话读得太多了“我希望在将文件从 Windows 资源管理器拖到 HTML 页面上的元素上时获得相同的数据 [as]可丢弃”。但是让我们看看这个新的 plkr 是否有帮助
新 pluker 上的 drop listener 没有检查 dataTransfer 文件。似乎没有办法将文件附加到 dataTransfer 以便 drop 事件可以将它们作为文件接收?
您可以在 setData 中传递数据 URI,并在 drop 事件中使用 getData。虽然 FileReader 加载事件异步返回结果。【参考方案2】:
最简单的方法是“添加项目”:
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'));
只有你需要它来调整你的文件到文件类型:)
【讨论】:
aFileParts 在这段代码中的作用是什么?我不明白它的功能...... 这只是一个模拟,因为new Blob()
需要这个参数。你可以在那里创建任何你想要的东西:)
是的,这是真的。在我的例子中,它是一个“已经创建”的 blob,所以我只需要在 newFile() 中传递它。以上是关于如何使用 Javascript 将文件添加到已经存在的 dataTransfer 对象中的主要内容,如果未能解决你的问题,请参考以下文章