javascript - 提供文件数据时触发 'drop'事件

标签 javascript dom-events

问题

我如何在提供文件的同时触发字段的 drop 事件,我在加载时无权访问

详情

有一个页面有一个字段,在该字段上附加了一个 drop 监听器,该监听器在放置时处理图像。我希望能够通过粘贴 图像来使用此过程。我知道如何从粘贴中获取文件,但我不知道如何发送包含该文件的 drop 事件。

障碍是:

  • 代码被混淆了,我无法通过名称访问与监听器链接的函数。
  • drop 监听器附加到元素后无法获得。 似乎有一些方法可以在控制台中执行此操作,但不能通过脚本执行。
  • 我不控制页面呈现;即我无法拦截事件监听器添加。
  • Vanilla Javascript & 只能在 Chrome(扩展)中运行。
  • 此页面是用原版构建的;即没有 jQuery 或任何东西。

有没有人知道如何处理这个任务?

我正在调查 DragEvent但是 “虽然这个接口(interface)有一个构造函数,但不可能从脚本创建一个有用的 DataTransfer 对象,因为 DataTransfer 对象有一个处理和安全模型,在拖放过程中由浏览器协调。”

我看到了一种可能的方法 https://stackoverflow.com/a/39066443/1004274但我想用它的数据模拟一个真实 drop 事件,即传递一个我通过 clipboardData.items[0].getAsFile(); 获得的文件,而不仅仅是文本。

最佳答案

您可以伪造 drop 事件,并伪造其中的几乎所有内容。您将遇到的问题是触发默认事件,例如通过拖放在选项卡中打开文件。原因不是因为 dataTransfer 对象受到保护,而是事件不受信任。通过拥有受信任的事件和 protected 数据传输,您可以确保不会将数据传递给受信任的事件,并且不会使用不需要的数据触发默认事件。

但是根据 drop 函数访问被删除文件的方式,您可以使用伪造的 drop 事件和伪造的 dataTransfer 对象来欺骗它。请参阅此 fiddle 以了解其工作原理:

var a = document.getElementById('link');
var dropZone1 = document.getElementById('dropZone1');
var dropZone2 = document.getElementById('dropZone2');
var fakeDropBtn = document.getElementById('fakeDropBtn');

dropZone1.addEventListener('dragover', function(e) {
  e.preventDefault();
});

dropZone2.addEventListener('dragover', function(e) {
  e.preventDefault();
});

dropZone1.addEventListener('drop', function(e) {
  // This first drop zone is simply to get access to a file.
  // In your case the file would come from the clipboard
  // but you need to work with an extension to have access
  // to paste data, so here I use a drop event
  e.preventDefault();
  fakeDropBtn.classList.remove('disabled');
  dropZone2.classList.remove('disabled');
  var fileToDrop = e.dataTransfer.files[0];

  // You create a drop event
  var fakeDropEvent = new DragEvent('drop');
  // You override dataTransfer with whichever property
  // and method the drop function needs
  Object.defineProperty(fakeDropEvent, 'dataTransfer', {
    value: new FakeDataTransfer(fileToDrop)
  });

  fakeDropBtn.addEventListener('click', function(e) {
    e.preventDefault();

    // the fake event will be called on the button click
    dropZone2.dispatchEvent(fakeDropEvent);
  });
});



dropZone2.addEventListener('drop', function(e) {
    e.preventDefault();
  // this is the fake event being called. In this case for 
  // example, the function gets access to dataTransfer files.
  // You'll see the result will be the same with a real
  // drop event or with a fake drop event. The only thing
  // that matters is to override the specific property this function
  // is using.
  var url = window.URL.createObjectURL(e.dataTransfer.files[0]);
  a.href = url;
  a.click();
  window.URL.revokeObjectURL(url); 
});

function FakeDataTransfer(file) {
  this.dropEffect = 'all';
  this.effectAllowed = 'all';
  this.items = [];
  this.types = ['Files'];
  this.getData = function() {

    return file;
  };
  this.files = [file];
};

https://jsfiddle.net/5m2u0tux/6/

关于javascript - 提供文件数据时触发 'drop'事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39487340/

相关文章:

php - 无法将 ajax 填充的字段传递给 php

javascript - onMouseOver、超链接和 rel...帮助我 :(

javascript - Javascript(NodeJS) 如何处理有关事件的范围和上下文

javascript - 将鼠标悬停在动画中的 HTML-5 Canvas 图像上即可播放/暂停

javascript - React-我应该使用 promise 来设置状态吗?

javascript - 如何用图像替换 3 个随机字符

javascript - JavaScript 的堆叠 DIV 点击事件

javascript - 高效检测单页应用中的 DOM 变化

javascript - 将数据 URI 合并到 APNG 中?

javascript - 为什么工具提示自动放置不能正常工作?