IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 基于layui.upload.js 拖拽文件/文件夹上传下载 -> 正文阅读

[JavaScript知识库]基于layui.upload.js 拖拽文件/文件夹上传下载

作者:token punctuation

前言

项目需求完成文件上传,可以拖拽上传文件/文件夹,基于layui的upload.js增强完成该需求

js代码

layui的引入和使用就不说了,懂的都懂,不懂去学习一下,废话不多说,直接上代码.基于upload.js自定义uploadFile.js用于实现需求功能

/**
 * author: wz
 * referenceAddress:文件,文件夹上传
 */
layui.define(["layer", "upload",'element','table'], function (e) {
    "use strict";
    var $ = layui.$, layer = layui.layer, upload = layui.upload,element=layui.element,table=layui.table,
        tableArr=[],datas=[],model={},unfinishedList=[],beingList=[],timer=null,beingCount=10,beingFlag=false,timerTable=null,keepTime=0;
    //配置server token
    var conf = JSON.parse(localStorage.conf);
    var server = conf.file.server;
    var token = conf.file.token;
    function renderFile(option) {
        var uploadInst=upload.render({
            elem: '#' + option.id,
            auto: option.auto||false,
            accept: option.accept,
            acceptMime: option.acceptMime,
            exts: option.exts,
            size: option.size||0,
            multiple: option.multiple||true,
            number: option.number||0,
            choose:function (obj) {
                    var loadingIndex = layer.load(2, { //icon支持传入0-2
                        shade: [0.5, 'gray'], //0.5透明度的灰色背景
                        content: '读取文件...',
                        success: function (layero) {
                        }
                    });
                    obj.preview(function (index, file) {
                        loadingIndex="";
                        layer.closeAll();
                        var fileUuid=uuid();
                        uploadServer(file,fileUuid,"0",file.webkitRelativePath,option);
                    });
                    setTimeout(function () {
                        if(loadingIndex){
                            layer.closeAll();
                            layer.msg("上传类型错误,请检查!", {icon: 5});
                        }
                    },20000);
            }
        });
        selectEvent(option.id);
    }

    function selectEvent(id) {
        $('#' + id).bind("dragover",function (e) {
            $(this).css("background","#e9f5fe");
        })
        $('#' + id).bind("dragleave",function (e) {
            $(this).css("background","");
        })
        $('#' + id).bind("mouseover",function (e) {
            $(this).css("background","#e9f5fe");
        })
        $('#' + id).bind("mouseout",function (e) {
            $(this).css("background","");
        })
    }

    //上传中转站
    function uploadServer(file,fileUuid,type,path,option,serialNumber) {
        var parentId=option.parentId;
        if(type=='0'){//文件上传
            tableData(file,fileUuid,option.parentId,option.nodeId,"0");
        }else {//文件夹上传
            if(path){
                var split=path.split("/");
                for (var i = 0; i < split.length; i++) {
                    if(i<=split.length-2){
                        parentId=folderLoading(split[i],parentId,option.nodeId,serialNumber);
                    }else {
                        tableData(file,fileUuid,parentId,option.nodeId,"1");
                    }
                }
            }
        }
        unfinishedList.push({
            file:file,//文件对象
            type:type,//文件上传
            path:path,//文件路径
            uuid:fileUuid,//唯一标识
            parentId:parentId
        });
        if(timer==null){
            timer=setInterval(function (d) {
                    if(unfinishedList.length>0){
                        if(beingList.length<beingCount){//控制同时上传个数
                            var diff=beingCount-beingList.length;
                            for (let i = 0; i <diff ; i++) {
                                if(unfinishedList.length>i){
                                    beingList.push(unfinishedList[i].uuid);
                                    uploadDone(option,unfinishedList[i].file,unfinishedList[i].uuid,unfinishedList[i].parentId);
                                }
                            }
                            for (let i = 0; i <diff; i++) {
                                if(unfinishedList.length>0){
                                    unfinishedList.splice(0,1);
                                }
                            }
                        }
                    }else {//上传完成
                        if(timer!=null){
                            clearInterval(timer);
                            timer=null;
                        }
                    }
            },500);
        }
        if(timerTable==null){
            timerTable=setInterval(function (d) {
                keepTime++;//计时
                if(unfinishedList.length==0&&beingList.length==0){
                    reloadTable(option,true);
                    clearInterval(timerTable);
                    timerTable=null;
                }else {
                    reloadTable(option,false);
                }
            },1000);
        }
    }


    /*
    文件夹拖拽上传
    在 drop 事件中获取 e.dataTransfer.items ,是一个 DataTransferItemList 对象,遍历得到 DataTransferItem 对象
    用 webkitGetAsEntry 方法得到 FileSystemEntry 对象
    根据 isFile 属性判断 entry 是文件还是文件夹。是文件的话,用 file 方法获取 File 对象;是文件夹的话,递归地用 reader 读取包含的文件
    原文链接:https://blog.csdn.net/tangran0526/article/details/104156857
    * */
    function scanFiles(e,option) {
        e.preventDefault();
        //var files=[];
        var item=e.dataTransfer.items;//获取DataTransferItemList 对象
        if(item&&item.length>0){
            var serialNumber=uuid();//同一上传批次序列号下的同名文件夹不重复添加
            for (var it of item) {
                var entry=it.webkitGetAsEntry();//获取 FileSystemEntry 对象
                fileReader(entry,function (file, path) {
                    uploadServer(file,uuid(),"1",path,option,serialNumber);
                });
            }
        }
    }


    function fileReader(entry,succ) {
        if (entry.isFile) {
            entry.file(file => {
                // 这里的 file.webkitRelativePath 都是 "" ,不是我们想要的.
                // entry.fullPath 是前面带斜杠的,要把斜杠去掉的
                let path = entry.fullPath.substring(1);
                succ(file,path);
            });
        } else {
             getEntryDirectoryFiles(entry).then(data=>{
                 data.forEach(_this=>{fileReader(_this,succ);});
             });

        }
    }

    // 获取文件夹所有子集
     function getEntryDirectoryFiles(entry) {
        const reader = entry.createReader()
        // 一次最多只能读100,防止出现文件夹内文件个数过多,加一个变量收集最新的结果
        let res = []
         return read();
        async function read() {
            const files = await new Promise((resolve, reject) =>
                reader.readEntries((entries) => {
                    // 只上传一层文件,过滤文件夹中包含的文件夹
                    //const fileEntries = entries.filter((entry) => entry.isFile)
                    const filesPromise = entries.map((e) => new Promise((resolve) =>resolve(e)))
                    Promise.all(filesPromise).then(resolve)
                }, reject)
            )
            // 保存当前读取文件
            res = [...res, ...files]
            // chrome浏览器一次读取最多获取100个文件,多于100个需要再次读取
            if (files.length < 100) {
                return res
            }
            return read()
        }
    }

    async function read(entry,res) {
        const reader = entry.createReader();
        for (let i = 0; i < 3; i++) {
        await new Promise((resolve, reject) =>{
            debugger;
                reader.readEntries((entries) => {
                    debugger;
                    console.log(entries.length);
                    // 只上传一层文件,过滤文件夹中包含的文件夹
                })
            }
        )
        }
    }


    function renderDrop(option) {
        $("#"+option.dropId).click(function (e) {
            $("#"+option.id).click();
        });
        // 获取文件夹
        document.getElementById(option.dropId).ondrop =  (e) => {
            scanFiles(e,option);
        }
        selectEvent(option.dropId);
    }

    function renderFolder(option) {//上传文件夹
        $("#"+option.id).change(function(){
            var files = this.files,serialNumber=uuid();
            for (var file of files) {
                uploadServer(file,uuid(),"1",file.webkitRelativePath,option,serialNumber)
            }
            files=null;
        });
    }


    function uploadDone(option,file,fileUuid,parentId) {
        //if(option.tableId)reloadTable(option,false);
        burstUpload(option,file,fileUuid,function (fileID, res, name) {//文件上传完成回调
            resLoading(res,fileID,option,parentId);
            if(option.tableId){
                var fin=tableArr.findIndex(a=>{return a.fileUuid==fileID});
                if(fin>=0){
                    tableArr[fin].percent="100.00";
                    tableArr[fin].fileurl=res.url;
                    // if(unfinishedList.length==0&&beingList.length==0){
                    //     reloadTable(option,true);
                    // }else {
                    //     reloadTable(option,false);
                    // }
                }
            }
            if (typeof option.allBurst != 'undefined' && option.allBurst instanceof Function) {
                option.allBurst(fileID, res, name);//每次单个文件上传成功以后的回调
            }
        });
    }

    function resLoading(res,fileID,option,parentId) {//装载文件柜对象
        model['filetype']=getFileType(res.name);
        model['fileurl']=res.url;
        model['filename']=res.name;
        model['fileshuffix']=res.type;
        model['filesize']=res.size;
        model['thumbnail']=res.thumbnailPath;
        model['sizeDes']=res.sizeDes;
        model['publishtime']=res.timeDes;
        model['parentId']=parentId;
        model['fileUuid']=fileID;
        model['nodeId']=option.nodeId;
        datas.push(model);
        model={};
        //计算文件夹大小
        // if(parentId){
        //     getFileSize(parentId,res.size||0);
        // }
        if (typeof option.onChange != 'undefined' && option.onChange instanceof Function) {
            option.onChange(datas);
        }
    }

    function getFileType(fileName) {//根据文件后缀判断文件类型
        var docReg = /(doc|docx|rtf|xls|xlsx|ppt|pptx|pdf)$/;
        var imgReg = /(jpg|jpeg|png|gif|cad)$/;
        var mp3Reg = /(mp3)$/;
        var mp4Reg = /(mp4|avi)$/;
        var zipReg = /(zip|rar|war)$/;
        var fileReg = /(bak|txt|sql|exe|bat|md|htm|html)$/;
        if (fileName) {
            var name = fileName.toLocaleLowerCase();
            if (docReg.test(name)) {
                return 1;
            } else if (imgReg.test(name)) {
                return 2;
            } else if (mp3Reg.test(name)) {
                return 3;
            } else if (mp4Reg.test(name)) {
                return 4;
            } else if (zipReg.test(name)) {
                return 5;
            } else if (fileReg.test(name)) {
                return 6;
            } else {
                return 7;
            }
        } else {
            return 7;
        }
    }

    //生成文件夹
    function folderLoading(filename,parentId,nodeId,serialNumber) {
        var fileUuid=parentId;
        var fin=datas.findIndex(a=>{return a.filename==filename&&a.parentId==parentId&&a.nodeId==nodeId});
        if(fin>=0){
            if(datas[fin].serialNumber!=serialNumber){
                filename=filename+"(1)";
                fileUuid=folderLoading(filename,parentId,nodeId,serialNumber);
            }else {
                fileUuid=datas[fin].fileUuid;
            }
        }else {
            fileUuid=uuid();
            model['filetype']=0;
            model['fileurl']='';
            model['filename']=filename;
            model['fileshuffix']='';
            model['filesize']=0;
            model['thumbnail']='';
            model['sizeDes']='';
            model['publishtime']=null;
            model['parentId']=parentId;
            model['fileUuid']=fileUuid;
            model['nodeId']=nodeId;
            model['serialNumber']=serialNumber;
            datas.push(model);
            model={};
        }
        return fileUuid;
    }

    function tableData(file,fileUuid,parentId,nodeId,filewar) {
        model.fileUuid=fileUuid;
        model.filename=file.name||"/";
        model.filesize=file.size||0;
        model.filetype=file.type||"/";
        model.percent="0";
        model.filewar=filewar;//上传方式
        model.fileurl='';//文件路径
        model.parentId=parentId;
        model.nodeId=nodeId;
        model.file=file;
        if(tableArr&&tableArr.length>0){
            tableArr.unshift(model);
        }else {
            tableArr.push(model);
        }
        model={};
    }

    //计算文件夹大小
    function getFileSize(parentId,fileSize) {
        var fin=datas.findIndex(a=>{return a.fileUuid==parentId});
        if(fin>=0){
            datas[fin].filesize=parseInt(datas[fin].filesize)+parseInt(fileSize);
            getFileSize(datas[fin].parentId,datas[fin].filesize);
        }
    }

    function uuid() {
        var s = [];
        var hexDigits = "0123456789abcdef";
        for (var i = 0; i < 36; i++) {
            s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
        }
        s[14] = "4";  // bits 12-15 of the time_hi_and_version field to 0010
        s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);  // bits 6-7 of the clock_seq_hi_and_reserved to 01
        s[8] = s[13] = s[18] = s[23] = "-";

        return s.join("");
    }

    function picTime(val) {
        var hh = parseInt(val/3600);
        if(hh<10) hh = "0" + hh;
        var mm = parseInt((val-hh*3600)/60);
        if(mm<10) mm = "0" + mm;
        var ss = parseInt((val-hh*3600)%60);
        if(ss<10) ss = "0" + ss;
        var length = hh + ":" + mm + ":" + ss;
        if(val>0){
            return length;
        }else{
            return "0秒";
        }
    }

    //移除文件夹,移除依据:如果是该文件是该目录下唯一文件则移除该目录
    function removeDatas(index,option) {
        var data=datas[index];
        datas.splice(index,1);
        var pin=datas.findIndex(a=>a.fileUuid==data.parentId);
        var pData=datas[pin];
        if(pin>=0){
            //查询是否还有子节点
            var cin=datas.findIndex(a=>a.parentId==pData.fileUuid);
            if(cin<0){//没有子节点,也要被删除
                removeDatas(pin,option);
            }
        }
        if (typeof option.onChange != 'undefined' && option.onChange instanceof Function) {
            option.onChange(datas);
        }
    }

    function reloadTable(option,flag) {
        var str='<script type="text/html" id="toolbar"><button class="layui-btn layui-btn-danger layui-btn-sm" lay-event="del">删除</button></script>'
        var allCount=tableArr.length,successCount=0,failCount=0;
        table.render({
            elem: '#'+option.tableId
            ,data:tableArr
            ,toolbar : str
            //,height : 'full-200'
            ,cols: [[ //表头
                {type:'checkbox'}
                ,{type:'numbers',title: '序号'}
                ,{field: 'fileUuid', title: 'uuid', hide: true,align:'center'}
                ,{field: 'filewar', title: '上传方式',align:'center',templet:function (d) {
                    if(d.filewar=='1')return "文件夹上传";
                    return "文件上传";
                    }}
                ,{field: 'filename', title: '文件名称',align:'center'}
                ,{field: 'filesize', title: '文件大小',align:'center'}
                ,{field: 'filetype', title: '文件类型',align:'center'}
                ,{field: 'percent', title: '上传进度',align:'center',width:"20%",templet:function (d) {//layui-bg-blue
                    if(d.percent=="100.00"){
                        return '<div class="layui-progress layui-progress-big layui-progress-rate" lay-filter="process'+d.fileUuid+'" lay-showPercent="true">' +
                            '<div class="layui-progress-bar layui-bg-blue" lay-percent="'+d.percent+'%" id="procent'+d.fileUuid+'"></div></div>'
                    }else {
                        return '<div class="layui-progress layui-progress-big layui-progress-rate" lay-filter="process'+d.fileUuid+'" lay-showPercent="true">' +
                            '<div class="layui-progress-bar" lay-percent="'+d.percent+'%" id="procent'+d.fileUuid+'"></div></div>'
                    }

                    }}
                ,{title: '操作',align:'center',width:"10%",templet : function (d) {
                        if(d.percent=="100.00"){
                            successCount++;
                            return '<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>';
                        }else if(d.percent=="0"&&flag){
                            failCount++;
                            return '<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="tautology">重试</a>';
                        }else {
                            return '';
                        }
                    }}
            ]]
            ,limit:9999999
            ,done:function (res, curr, count) {
                if(option.detailsId){
                    var ps=successCount==0?0:((successCount*100)/allCount).toFixed();
                    var detailStr='<div class="layui-fluid" style="padding: 0"><div class="file_upload_title">' +
                        '<span>共&nbsp;<b>'+allCount+'</b>&nbsp;个文件,上传完成:<b>'+successCount+'</b>,' +
                        '正在上传:<b>'+beingList.length+'</b>,上传失败:<b>'+failCount+'</b>,总进度:<b>'+ps+'%</b>,' +
                        '总用时:<b>'+picTime(keepTime)+'</b></span></div></div>';
                    $("#"+option.detailsId).html(detailStr);
                }
                var h=$(document).height();
                var pss=1-(ps/100);
                $(document).scrollTop((h*pss).toFixed(2));
                element.render('progress');
            }
        });
        //头工具栏事件
        table.on('toolbar('+option.tableId+')', function(obj) {
            var checkStatus = table.checkStatus(obj.config.id);
            var data = checkStatus.data;
            switch (obj.event) {
                case 'del':
                    if (data.length == 0) {
                        layer.alert('请选择您想要移除的数据!');
                        break;
                    }
                    var urls = "";
                    for (var i = 0; i < data.length; i++) {
                        if(data[i].fileurl)urls += data[i].fileurl + "&;&";
                    }
                    layer.confirm("确定移除文件?", {
                        icon : 3,
                        title : '移除'
                        ,btn: ["确定","取消"] //按钮
                    }, function(index) {
                        $.ajax({
                            url: server + 'del',
                            headers: {
                                Authorization: token
                            },
                            type: "POST",
                            data: {url:urls,decollator:"&;&"},
                            success: function (res) {
                                if (res.code === 0) {
                                    for (var datum of data) {
                                        var fin=tableArr.findIndex(a=>{return a.fileUuid==datum.fileUuid});
                                        if(fin>=0){
                                            tableArr.splice(fin,1);
                                        }
                                        var din=datas.findIndex(a=>{return a.fileUuid==datum.fileUuid});
                                        if(din>=0){
                                            removeDatas(din,option);
                                        }
                                    }
                                    reloadTable(option);
                                    layer.msg("移除成功", {icon: 6});
                                } else {
                                    layer.msg("移除失败", {icon: 5});
                                }
                            },
                            error: function (msg) {
                                layer.msg("移除失败", {icon: 5});
                                return false;
                            }
                        });
                    });
                    break;
            }
        });
        //行工具条
        table.on('tool('+option.tableId+')', function(obj) {
            var data = obj.data;
            switch (obj.event) {
                case 'del':
                    layer.confirm("确定移除文件?", {
                        icon : 3,
                        title : '移除'
                    }, function(index) {
                        $.ajax({
                            url: server + '/del',
                            headers: {
                                Authorization: token
                            },
                            type: "POST",
                            data: {url:data.fileurl,decollator:"&;&"},
                            success: function (res) {
                                if (res.code === 0) {
                                    var fin=tableArr.findIndex(a=>{return a.fileUuid==data.fileUuid});
                                    if(fin>=0){
                                        tableArr.splice(fin,1);
                                        reloadTable(option);
                                    }
                                    var din=datas.findIndex(a=>{return a.fileUuid==data.fileUuid});
                                    if(din>=0){
                                        removeDatas(din,option);
                                    }
                                    layer.msg("移除成功", {icon: 6});
                                } else {
                                    layer.msg("移除失败", {icon: 5});
                                }
                            },
                            error: function (msg) {
                                layer.msg("移除失败", {icon: 5});
                                return false;
                            }
                        });
                    });
                    break;
                case 'tautology':
                    uploadDone(option,data.file,data.fileUuid,data.parentId);
                    break;
            }
        });
    }

    function uploadFail(option,fileID) {
        if(fileID){//上传完成移除正在上传标记
            var fin=beingList.findIndex(a=>{return a==fileID});
            if(fin>=0) beingList.splice(fin,1);
            // var uin=tableArr.findIndex(a=>{return a.fileUuid==fileID});
            // if(uin>=0) tableArr.splice(uin,1);
        }
        //reloadTable(option,false);
    }

    function burstUpload(option, file, fileID, succ) {
        //文件上传//
        var TMap = new Map();
        var arrayAJAX = [];
        var timer = setTimeout(function () {//每个文件异步处理
            var name = file.name,        //文件名
                size = file.size,        //总大小
                succeed = 0;

            var shardSize = 5 * 1024 * 1024;    //以5MB为一个分片
            var shardCount = Math.ceil(size / shardSize);   //总片数

            var uuid = fileID;//文件id
            var time = new Date().getTime();//时间戳

            for (var i = 0; i < shardCount; ++i) {
                //文件分块上传
                // setTimeout(function () {//每个分块异步处理
                //计算每一片的起始与结束位置
                var start = i * shardSize, end = Math.min(size, start + shardSize);
                var objf = file.slice(start, end);
                //构造一个表单,FormData是HTML5新增的
                var form = new FormData();
                form.append("name", name);  //文件名
                form.append("size", size);  //大小
                form.append("uuid", uuid);//上传id
                form.append("time", time);//时间
                form.append("file", objf);  //slice方法用于切出文件的一部分
                form.append("chunks", shardCount);   //总片数
                form.append("chunk", i);        //当前是第几片
                //Ajax提交
                arrayAJAX.push($.ajax({
                    url: server + 'upload',
                    headers: {
                        Authorization: token
                    },
                    type: "POST",
                    data: form,
                    //async: false,         //异步
                    processData: false,  //很重要,告诉jquery不要对form进行处理
                    contentType: false,  //很重要,指定为false才能形成正确的Content-Type
                    dataType: "json",
                    mimeType: "multipart/form-data",
                    success: function (res) {
                        if (res.code === 0) {
                            ++succeed;
                            var percent = succeed / shardCount * 100;
                            var progress = percent.toFixed(2);
                            $("#procent"+fileID).attr('lay-percent',progress+'%');
                            element.init();
                            element.progress('process' + fileID, progress + "%");//更新进度条
                            if (typeof option.burst != 'undefined' && option.burst instanceof Function) {
                                option.burst(uuid, progress, res, name);//每次分片上传成功以后的回调
                            }

                            //Uploader.proFile(option, uuid, progress);//列表进度更新
                            if (succeed === shardCount) {//每完成一个 修改完成样式
                                $("#procent"+fileID).attr('class',"layui-progress-bar layui-bg-blue");
                                if(fileID){//上传完成移除正在上传标记
                                   var fin=beingList.findIndex(a=>{return a==fileID});
                                   if(fin>=0) beingList.splice(fin,1);
                                }
                                succ(uuid, res, name);//成功回调
                            }
                        } else {
                            layer.msg(res.msg);
                            uploadFail(option,fileID);
                        }
                    },
                    error: function (msg,textStatus) {
                        if(msg.readyState==0){
                            layer.msg("文件读取失败,请检查!");
                        }else {
                            layer.msg("文件服务器异常,请联系管理员!");
                        }
                        uploadFail(option,fileID);
                        return false;
                    }
                }));
            }
        }, 10);//文件上传,异步处理
        TMap.set(fileID, arrayAJAX);
        option.timer = TMap;
    }
    var uploadFile = {
        initFile:function (option) {
            if (option.hasOwnProperty('id')&&option.hasOwnProperty('parentId')&&option.hasOwnProperty('nodeId')){
                renderFile(option);
            }else {
                layer.msg("文件上传组件初始化参数丢失,请检查", {icon: 5});
            }
        },
        initFolder:function (option) {
            if (option.hasOwnProperty('id')&&option.hasOwnProperty('parentId')&&option.hasOwnProperty('nodeId')&&option.hasOwnProperty('dropId')){
                renderDrop(option);
                renderFolder(option);
            }else {
                layer.msg("文件夹上传组件初始化参数丢失,请检查", {icon: 5});
            }
        },
        downFile:function (url, params,async) {
            if (url != null) {
                if(async){//异步下载
                    if (params != null) {
                       Object.keys(params).forEach(function (item, i, arr) {
                           if(i==0){
                               url+="?"+item+"="+params[item];
                           }else {
                               url+="&"+item+"="+params[item];
                           }
                       })
                    }
                    var xhr = new XMLHttpRequest();
                    xhr.open('POST', url, true);        // 也可以使用POST方式,根据接口
                    xhr.responseType = "blob";    // 返回类型blob
                    xhr.onload = function () {
                        if (this.status === 200) {
                            var blob = this.response;
                            var filename=xhr.getResponseHeader("Content-Disposition").split(";")[1].split("filename=")[1];//从响应头中获取文件名称
                            var reader = new FileReader();
                            reader.readAsDataURL(blob);    // 转换为base64,可以直接放入a表情href
                            reader.onload = function (e) {
                                var a = document.createElement('a');
                                a.download = filename;//下载文件名
                                a.href = e.target.result;
                                $("body").append(a);    // 修复firefox中无法触发click
                                a.click();
                                $(a).remove();
                            }
                        }
                    };
                    // 发送ajax请求
                    xhr.send()
                }else{//同步提交,form默认提交方式
                    var form = $("<form></form>").attr("action", url).attr("method", "post");
                    if (params != null) {
                        for (var key in params) {
                            form.append($("<input/>")
                                .attr("type", "hidden")
                                .attr("name", key)
                                .attr("value", params[key])
                            );
                        }
                        form.appendTo('body').submit().remove();
                    }
                }
                return false;
            }else {
                layer.msg("未找到下载连接,请检查!", {icon: 5});
            }
        }
    };
    //输出test接口
    e('uploadFile', uploadFile);
});

页面使用(我这里用的是uploader.jsp)

<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>模块系统</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport"
	content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="../static/layui/css/layui.css" media="all">
<link rel="stylesheet" href="../static/layuiadmin/style/admin.css" media="all">
<link rel="stylesheet" href="../static/library.css" media="all">
<link rel="stylesheet" href="../static/modules/icon/iconfont.css" media="all">
	<style>
		html{ background-color: #fff;}
		body{ padding: 0 15px;}
		.layui-upload-drag{ width: 100%; padding: 5px 10px; box-sizing: border-box; border: dashed 1px #ccc;}
		.layui-upload-drag p{ height: 26px; line-height: 26px;}
		.layui-upload{ position: relative; width: 100px;}
		.layui-upload input{ width: 100%; height: 100%; position: absolute; top: 0; left: 0; z-index: 99; opacity: 0;}
		#upload-btn{ width: 100%; height: 35px; line-height: 35px; color: #fff; background: linear-gradient(to right, #1E9FFF,#60a0ff);
		   border-radius: 5px; border: 0;}
		#upload-btn span{ font-size: 14px; color: #fff;}
		#upload-btn i{ display: inline-block; margin-right: 2px; font-size: 13px; color: #fff;}
	</style>
</head>
<body>
	<div class="file_locat">
		<div class="file_tab">
			<ul>
				<li class="file_tab_active">
					<p>文件上传</p>
				</li>
				<li>
					<p>文件夹上传</p>
				</li>
			</ul>
			<div class="file_tab_line"></div>
		</div>
		<div class="file_contain">
			<ul>
				<li class="file_act">
					<div class="layui-fluid" style="padding: 0">
						<div class="file_upload_title">文件上传:</div>
						<div class="layui-inline" style="width: 50%">
							<div class="layui-upload-drag" id="fileUpload">
								<p style="font-weight: bold; font-family: arial, sans-serif; font-size: 12px">点击上传,或将文件拖拽到此处</p>
							</div>
						</div>
					</div>
				</li>
				<li>
				<input height="100%" type='file' id="folderUpload" hidden webkitdirectory multiple="multiple">
					<div class="layui-fluid" style="padding: 0">
						<div class="file_upload_title">文件夹上传:</div>
						<div class="layui-inline" style="width: 50%">
							<div class="layui-upload-drag" id="folderUp">
								<p style="font-weight: bold; font-family: arial, sans-serif; font-size: 12px">点击上传,或将文件夹拖拽到此处</p>
							</div>
						</div>
					</div>
				</li>
			</ul>
			<div id="uploadDetails"></div>
		</div>

	</div>
	<table id="fileTable" lay-filter="fileTable"></table>

	<script src="../static/layui/layui.js"></script>
	<script>
		var uploadFile = [];
		var uploadImg =[];
		var parentId='${parentId}';
		var nodeId='${nodeId}';
		var files = [];
		// 阻止浏览器打开新标签,ondrop/ondragover/ondragenter(最好加上这个防兼容问题)
		window.ondragover = (e) => e.preventDefault();
		layui.config({base: '../static/modules/'})
				.extend({uploadFile: 'uploader/uploadFile'})
		.use(['element','form','uploadFile','upload'], function () {
			var $ = layui.$;
			var element = layui.element;
			var form = layui.form;
			var uploadFile = layui.uploadFile;
			uploadFile.initFile({
				id: 'fileUpload',
				accept: 'file',
				acceptMime: '',
				exts: '',
				size: 0,
				multiple:true,
				number:0,
				tableId:'fileTable',
				detailsId:'uploadDetails',//上传详情
				parentId:parentId,
				nodeId:nodeId,
				onChange:function (param) {
					files=param;
				}
			});
			uploadFile.initFolder({
				id: 'folderUpload',
				tableId:'fileTable',
				dropId:'folderUp',
				detailsId:'uploadDetails',//上传详情
				parentId:parentId,
				nodeId:nodeId,
				onChange:function (param) {
					files=param;
				}
			});
			var _aW = $(".file_tab ul").find(".file_tab_active").width();
			var _aP = $(".file_tab .file_tab_active").position();
			$(".file_tab .file_tab_line").css({ left: _aP, width: _aW});
			$(".file_tab li").on("click", function(){
				var aP = $(this).position();
				var aW = $(this).width();
				var fileIndex = $(this).index();
				// var text=$(this).text();
				// if(text.replace(/" "/g,"")=="文件夹上传"){
				// 	initFolder();
				// }else {
				// 	initFile();
				// }
				$(".file_tab li").removeClass("file_tab_active");
				$(this).addClass("file_tab_active");
				$(".file_tab .file_tab_line").css({left: aP.left, width: aW})
				$(".file_contain li").hide();
				$(".file_contain li").eq(fileIndex).show();
			});
		});
		function getFiles() {
			return files;
		}
	</script>
</body>
</html>

CSS文件

.layui-layer-title{
    display: flex;
    align-items: center;
}
.file_locat{
    position: fixed;
    left: 0;
    top: 0;
    z-index: 1000;
    box-sizing: border-box;
    width: 100%;
    padding: 0 15px 7px;
    background: #fff;
}
.file_upload_title{
    display: inline-block;
    line-height: 34px;
    margin-right: 5px;
}
.file_tab{
    border-bottom: solid 1px #e5e5e5;
    margin-bottom: 18px;
    position: relative;
}
.file_tab ul{
    overflow: hidden;
}
.file_tab li{
    float: left;
    padding: 15px 0;
    margin-right: 30px;
    cursor: pointer;
    position: relative;
}
.file_tab .file_tab_line{
    display: block;
    position: absolute;
    left: 0;
    bottom: 0;
    z-index: 9;
    height: 3px;
    background: #2492ef;
    transition: all 0.3s;
}
.file_tab .file_tab_active p{
    font-weight: bold;
    color: #2492ef;
}
.file_contain li{
    display: none;
}
.file_contain .file_act{
    display: block;
}
#uploadDetails{
    margin-top: 10px;
}
.file_upload_title span{
    color: #666;
}
.layui-progress-rate{
    margin-top: 5px;
}
.layui-table-view{
    margin: 170px 0 10px;
    background: #f9f9f9;
}
.layui-table-view .layui-table{
    width: 100%;
}
.layui-layer-btn{
    background-color: #f8f8f8;
    border-top: solid 1px #e1e1e1;
}
.layui-form-checked[lay-skin=primary] i{
    border-color: #7cc2fc !important;
    background-color: #57a1fd;
}
.layui-form-checkbox[lay-skin=primary]:hover i{
    border-color: #7cc2fc;
}

上传效果

在这里插入图片描述

总结

这个上传js中包含大量我认为值得记录的东西,所以写下来当备忘录,包括
上传文件夹获取文件及路径的处理,异/同步下载问题,上传分片问题,表格进度条问题,表格滚动条问题
,这些都是值得记录的

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-18 17:32:01  更:2022-05-18 17:33:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 19:39:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码