我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

苏南大叔说一个几年前很酷的功能的实现方式,就是拖拽上传功能。在网页上有个区域,拖拽文件进入后,并不是默认的打开文件,而是实现了文件的上传功能。

苏南大叔:如何实现文件拖拽上传功能?拖拽上传句柄包含什么信息? - 文件拖拽上传功能
如何实现文件拖拽上传功能?拖拽上传句柄包含什么信息?(图6-1)

苏南大叔的平行空间笔记本博客,记录苏南大叔和计算机代码的故事。测试环境:谷歌浏览器@108.0.5359.125。

前置文章

这里有几篇前置文章,可以帮助本文的理解。

本文的内容和下面这篇文章,其实很相似。下面的文章是利用常见的上传组件上传,本文中并没有上传组件,读取的是拖拽文件的句柄。参考文字:

苏南大叔:如何实现文件拖拽上传功能?拖拽上传句柄包含什么信息? - 运行截图
如何实现文件拖拽上传功能?拖拽上传句柄包含什么信息?(图6-2)

屏蔽js事件

首先,屏蔽了上传容器的几个拖拽事件,使用的方式是:e.preventDefault();。代码如下:

<div class="box">拖拽文件到这个位置</div>
<script>
    let drop_box = document.querySelector(".box");
    drop_box.addEventListener("dragenter", function () {
        console.log("进入"); // 只进入一次
    });
    drop_box.addEventListener("dragover", function (e) {
        e.preventDefault();
        console.log("over"); // 连续over
    });
</script>

苏南大叔:如何实现文件拖拽上传功能?拖拽上传句柄包含什么信息? - preventdefault
如何实现文件拖拽上传功能?拖拽上传句柄包含什么信息?(图6-3)

关于阻止事件冒泡的方法:

拿到拖拽文件句柄

drop_box.addEventListener(
    "drop",
    function (e) {
        e.preventDefault();
        var _files = e.dataTransfer.files; // 这个就相当于文件上传组件
        // doUpload(_files);
    },
    false
);

苏南大叔:如何实现文件拖拽上传功能?拖拽上传句柄包含什么信息? - 拿到句柄
如何实现文件拖拽上传功能?拖拽上传句柄包含什么信息?(图6-4)

这里利用容器的drop事件,监控了e.dataTransfer.files,这个就相当于文件上传组件的.files。对比如下:

方式代码
拖拽上传e.dataTransfer.files
组件点击上传document.getElementById("file_input").files

关于事件参数的传递:

构建FormData

拿到files对象后,就是构建上传表单对象FormData了。然后就是常规的ajax上传,这里依然使用了jquery来实现这个需求。

function doUpload(_files) {
    for (let i = 0; i < _files.length; i++) {
        var data2 = new FormData();
        data2.append("file", _files[i]);
        $.ajax({
            async: true,
            url: "upload.php",
            type: "POST",
            cache: false,
            processData: false,
            contentType: false,
            data: data2,
            timeout: 60000,
            success: function (json) {
                console.log(json);
            },
            error: function (json) { },
        });
    }
}

苏南大叔:如何实现文件拖拽上传功能?拖拽上传句柄包含什么信息? - ajax上传代码
如何实现文件拖拽上传功能?拖拽上传句柄包含什么信息?(图6-5)

完整代码

<script src="https://cdn.bootcss.com/jquery/3.1.0/jquery.min.js"></script>
<style>
    .box {
        width: 300px;
        height: 80px;
        border: 1px solid #ccc;
        line-height: 80px;
        text-align: center;
        color: #ccc;
    }
</style>
<div class="box">拖拽文件到这个位置</div>
<script>
    let drop_box = document.querySelector(".box");
    drop_box.addEventListener("dragstart", function (e) {
        e.preventDefault();
        console.log("进入"); // 只进入一次
    });
    drop_box.addEventListener("dragenter", function (e) {
        e.preventDefault();
        console.log("进入"); // 只进入一次
    });
    drop_box.addEventListener("dragover", function (e) {
        e.preventDefault();
        console.log("over"); // 连续over
    });
    drop_box.addEventListener(
        "drop",
        function (e) {
            e.stopPropagation();               // firefox必须加上这句话
            e.preventDefault();
            var _files = e.dataTransfer.files; // 这个就相当于文件上传组件
            doUpload(_files);
        },
        false
    );
    function doUpload(_files) {
        for (let i = 0; i < _files.length; i++) {
            var data2 = new FormData();
            data2.append("file", _files[i]);
            $.ajax({
                async: true,
                url: "upload.php",
                type: "POST",
                cache: false,
                processData: false,
                contentType: false,
                data: data2,
                timeout: 60000,
                success: function (json) {
                    console.log(json);
                },
                error: function (json) { },
            });
        }
    }
</script>

这里并不描述后端的实现代码,根据不同的后端语言,实现的方式很多。接收file参数代表的文件即可。
可以参考:

firefox特殊处理

关于阻止事件冒泡的语句:

e.stopPropagation();               // firefox必须加上这句话
e.preventDefault();

firefox浏览器中测试的时候,也会正常上传,同时还会自动打开文件(浏览器默认行为)。所以加上了.stopPropagation()阻止事件冒泡。

苏南大叔:如何实现文件拖拽上传功能?拖拽上传句柄包含什么信息? - 停止冒泡
如何实现文件拖拽上传功能?拖拽上传句柄包含什么信息?(图6-6)

事件冒泡的文章,请点击:

拖拽句柄里面包含的信息

e.dataTransfer.files里面,包含文件的基本信息。包括:

属性
lastModified1671180126355
lastModifiedDateFri Dec 16 2022 16:42:06 GMT+0800 (中国标准时间) {}
nameempty.png
size1163
typeimage/png
webkitRelativePath""

还可以使用FileReader来读取更详细的信息(比如文件的内容)。参考文字:

结束语

文件拖拽上传,感觉很神秘,其实就是获得e.dataTransfer.files对象,然后构造FormData就可以实现上传。更多文章,请参考:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   js    html