如何判断图像是从同一页面拖放还是拖放上传?

How to tell if an image is drag-drop from the same page or drag-drop uploaded?

我有一个页面,用户可以在其中将图像从一个部分拖放到某个区域。 drag-drop API 支持这一点。同时,我也支持用户从本地电脑拖放图片。

问题是我如何判断图像是从同一页面拖放还是上传的?以前用 Chrome < 96,我可以用 event.dataTransfer.files.length 来检测。如果是拖放,长度是0,如果是上传,长度是>0.

随着最新 Chrome 版本的更新,这已经发生了变化。如果 img src 来自远程,这会像以前一样正常工作。但是,我的图像是 base64 编码的,它将被视为 Chrome (length > 0) 中的文件。我对更长作品的检测。

这是我的代码笔上的一些可重现代码:https://codepen.io/lz100/pen/BaJVvWr

在Windows和Ubuntu上,当你拖动第一张图片(remote src)时,文件数为0,但是当你拖动第二张图片(base64)时,文件数为1。当你拖放一个本地文件时,文件数也是1。所以我无法分辨图像是从哪里来的。 MacOS 没有这个问题。

如果您在 Firefox 上尝试上面的代码,一切都会如我所愿。同一页面拖放文件数为 0,本地拖放文件数为 1,但使用 Safari 所有三种情况都给我 1,即使是远程 URL 一个。

也许我应该问,是否有一种跨平台、跨浏览器的可靠方法来判断图像是从同一页面拖放还是从本地文件拖放?

原来,如果你drag-drop一个本地源的文件,传输事件中是没有描述的,但是如果是从同一个网页传输的图片,我们可以手动添加一些描述。

比如我们可以在dragStart事件中添加一些数据,在drop事件中检测

function handleDragStart(e) {
  e.dataTransfer.setData('text/plain', 'not_uploaded');
  // ....
}

img.addEventListener('dragstart', handleDragStart, false);

function handleDrop(e) {
  e.preventDefault(); e.stopPropagation(); 
   
  /*If dragged from current page e.dataTransfer.getData("text/plain") will be "not_uploaded"*/
  if(e.dataTransfer.getData("text/plain") === "not_uploaded") {
    // do something
  } else {
    // do other thing
  }
}

el.addEventListener('drop', handleDrop, false);