假设:可以访问 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
发布的方法下面进行了调整,以在也就是说,我们必须向 ondrop 传递一个参数,这
- 有一个
字段和dataTransfer
数组子字段,其中包含选定的files
和File
- a
方法(没有主体的函数即可)。preventDefault
.addEventListener("drop")
事件中将
drop
附加到
dragstart
元素,将
File
对象传递到带有
Function.prototype.bind()
的绑定函数,该函数返回上述适当的对象,并在第三个参数处传递
once:true
.addEventListener()
,对于访问或创建
drop
对象的每个
dragstart
事件最多调用一次
File
事件。对象是只读的,
Array
用于将
File
对象存储在事件处理程序中普通
dataTransfer.files
对象内的
javascript
属性中。
注意: 接口应被视为“有风险” 因为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
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'));
只有您需要的是将文件调整为文件类型:)
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>