如何实现文件的拖拽上传?

753 阅读1分钟

下图是使用 iReader 阅读器 wifi 传书的一个截图,我们可以点击蓝色的选择文件按钮来选择文件,也可以直接把文件拖到这个界面。就我个人而言,更喜欢把文件拖过来上传的方式。如果有个网页有选择文件的功能,但是不支持拖拽上传,总让我觉得它很原始。

image.png

这个功能非常常用,那它是怎么做的呢?今天我们就写一个小的 Demo 来演示一下!

能实现这个功能主要是靠浏览器的 Drap API。很多同学可能不知道,当我们把电脑的文件拖动并放置目标,这样也会触发 drag 事件

上代码!

let dropTarget = document.getElementById('app');

function handleEvent(event) {
  event.preventDefault()

  if (event.type === 'drop') {
    const files = event.dataTransfer.files;
    const reader = new FileReader();
    
    reader.readAsDataURL(files[0]);

    reader.onload = () => {
      dropTarget.style.backgroundImage = reader.result;
      dropTarget.style.backgroundImage = `url(${reader.result})`   
    }
  }
}

dropTarget.addEventListener("drop", handleEvent);
dropTarget.addEventListener("dragenter", handleEvent);
dropTarget.addEventListener("dragover", handleEvent);

在代码的结尾,为什么我们要绑定三个事件呢?是为了取消 drag 过程的默认事件。

我们真正需要的只有 'drop' 这一个动作,所以我们做了 if 判断。

FileReader 对象读文件是异步的,虽然结果在 FileReader 对象的 result 属性里,但真正的结果要在 onload 事件触发后才拿的到。初始化,FileReader 对象的 onload 属性是 null,需要我们自己初始化这个函数。

最后就是 readAsDataURL 这个 API 了。它将内容数据的 URL 保存在了 FileReader 的 result 属性里。

其实有时候我们不需要将内容读过来,比如上面的那个需求,我们只需要拿到它的一个 URL ,让我们能在标签里显示就可以了。这种情况下,我们并不需要使用 FileReader ,有更简单的方法:window.URL.createObjectURL,它返回的是一个指向内存中地址的字符串。

import "./styles.css";

let dropTarget = document.getElementById('app');

function handleEvent(event) {
  event.preventDefault()

  if (event.type === 'drop') {
    // 下面三行有变化
    const files = event.dataTransfer.files;
    const url = window.URL.createObjectURL(files[0]);
    dropTarget.style.backgroundImage = `url(${url})`
  }

}

dropTarget.addEventListener("drop", handleEvent);
dropTarget.addEventListener("dragenter", handleEvent);
dropTarget.addEventListener("dragover", handleEvent);

今天就分享这一个小技巧,收。