首页 > 其他分享 >html5实现文件批量上传组件

html5实现文件批量上传组件

时间:2024-01-04 10:01:15浏览次数:29  
标签:function index obj 上传 html5 return 文件批量 config

一、概述

在html5中,相对于之前添加了不少新的元素和属性,在javascript中也添加了一些新的API,这些给我们的开发带来了很多便利。但由于各浏览器的发展步骤不一致,也导致了不同浏览器对html5支持的差异性。

 

二、实现原理

1.在该html5实现的文件批量上传组件中,我们主要是利用html5中的一些新属性和新API来达到我们的目的。具体如下:

(1)file input控件中的multiple属性。添加了该属性后,我们在选择文件时就可以进行多选。

(2)javascript File API和相应一些属性。利用这些新功能,我们可以获取到选择的文件集合以及文件的一些属性,如文件名,文件大小,文件类型等等。

(3)FormData。使用它可以向服务器提交key/value的键值对数据。

(4)通过XMLHttpRequest的onprogress来获取和更新文件上传进度。

上面就是用到的主要技术点,更多详细的部分可以参考源代码。

2.具体的流程。

(1)首先使用时需要提交选择按钮,上传按钮和列表显示的元素id,组件通过为选择按钮添加onmouseover事件来动态生成(如果尚未生成过)一个file input控件,并设置为透明,然后定位到鼠标可以触发的位置。所以当用户点击选择按钮时,实际上点击的是file input控件的浏览来浏览并选择文件。

(2)组件调用file控件的files来获取文件的集合,然后循环将文件显示成列表,文件名、文件类型、文件大小、文件上传状态等可以通过占位符来确定其显示与否以及显示的位置。

(3)通过为上传按钮添加click上传事件来实现上传,上传时通过FormData和Ajax逐个上传(服务端按照常规获取文件的方法来获取相应的文件并实现上传),并显示上传进度。

三、浏览器兼容性

适用浏览器:Chrome,Firefox,Safari,Opera,IE10 

除了IE之外的其他浏览器开始支持的版本没有详细了解和测试,电脑上都是它们目前的新版本,可以很好的支持。

四、使用方法

具体调用方法如下(说明看注释):

window.onload = function () {

$ling.html5Upload.config = {


selectButtonId: "selectButton",


uploadButtonId: "uploadButton",


fileProgressContainerId: "processContainer",


url: "upload.ashx",


fileTypes: "|.jpg|.jpeg|.txt|",


fileSize: 300 * 1024 * 1024, //这里的限制 要跟服务端对文件大小的限制一致 或者 小于服务器文件大小的限制


//回调可以调用三个参数 总数,成功数和失败数,如果不需要可以不传


callback: function (allCount, successCount, failCount) { alert(allCount + "/" + successCount + "/" + failCount); }


};


$ling.html5Upload.init();

};

  上面的配置config中还有下面列出来的5个属性,下面的值均为默认值,不配置时将显示默认值

failWord: "失败",//该文件上传失败时显示在百分比进度地方的提示显示
waitingWord: "等待", //该文件等待上传时显示在百分比进度地方的提示显示
fileTypeInvalidatedWord: "格式不支持", //格式不支持时显示在百分比进度地方的提示显示
fileSizeInvalidatedWord: "文件超出限制", //文件超出限制时时显示在百分比进度地方的提示显示
repeatSubmitWord: "请不要重复提交",//重复提交时的提示

  html代码如下:

<div>
    <input id="selectButton" type="button" value="Select" />
    <input id="uploadButton" type="button" value="Upload" />
    <div id="processContainer" style="display:none;">
        <div>{FileName} | {FileSize} | {FileType} | {UploadPercentage}</div>
    </div>
</div>

具体也可以看下载里面的例子。

五、源代码

具体代码:

(function () {
    //公开方法
    var html5Upload = {
        init: null
    };
    //默认配置
    html5Upload.configDefault = {
        selectButtonId: null,
        uploadButtonId: null,
        fileProgressContainerId: null,
        failWord: "失败",//该文件上传失败时显示在百分比进度地方的提示显示
        waitingWord: "等待", //该文件等待上传时显示在百分比进度地方的提示显示
        fileTypeInvalidatedWord: "格式不支持", //格式不支持时显示在百分比进度地方的提示显示
        fileSizeInvalidatedWord: "文件超出限制", //文件超出限制时时显示在百分比进度地方的提示显示
        repeatSubmitWord: "请不要重复提交", //重复提交时的提示
        fileTypes: null,
        fileSize: null,
        callback: null,
        url:null
    };
    //初始化事件
    html5Upload.init = function () {
        new Upload();
    };
    //上传事件构造函数
    function Upload() {
        this.config = html5Upload.config;
        this.config.failWord = !this.config.failWord ? html5Upload.configDefault.failWord : this.config.failWord;
        this.config.waitingWord = !this.config.waitingWord ? html5Upload.configDefault.waitingWord : this.config.waitingWord;
        this.config.repeatSubmitWord = !this.config.repeatSubmitWord ? html5Upload.configDefault.repeatSubmitWord : this.config.repeatSubmitWord;
        this.config.fileTypeInvalidatedWord = !this.config.fileTypeInvalidatedWord ? html5Upload.configDefault.fileTypeInvalidatedWord : this.config.fileTypeInvalidatedWord;
        this.config.fileSizeInvalidatedWord = !this.config.fileSizeInvalidatedWord ? html5Upload.configDefault.fileSizeInvalidatedWord : this.config.fileSizeInvalidatedWord;
    
        this.successCount = 0;
        this.failCount = 0;
    
        this.createFileInput();
        //绑定选择按钮事件
        addEvent("mousemove", document.getElementById(this.config.selectButtonId), function (obj, event) {
            return function (event) {
                obj.selectButtonMoveEvent(event);
            };
        } (this));
        //绑定上传按钮事件
        addEvent("click", document.getElementById(this.config.uploadButtonId), function (obj) {
            return function () {
                if (obj.isUploaded) {
                    alert(obj.config.repeatSubmitWord);
                    return;
                }
                obj.isUploaded = true;
                obj.uploadFile();
            };
        } (this));
    }
    //创建文件输入框
    Upload.prototype.createFileInput = function () {
        var id = Math.random();
        var fileInputId = ("html5UploadBox" + id).replace("0.", "");
        var fileInput = document.createElement("input");
        fileInput.id = this.fileInputId;
        fileInput.type = "file";
        fileInput.multiple = true;
        fileInput.style.position = "absolute";
        if (fileInput.filters) {
            fileInput.filters.alpha.opactity = 0;
        }
        else {
            fileInput.style.opacity = 0;
        }
        document.body.appendChild(fileInput);
        this.fileInput = fileInput;
        addEvent("change", this.fileInput, function (obj) {
            return function () {
                //重置属性值
                obj.progressPercentage = null;
                obj.isUploaded = false;
                obj.successCount = 0;
                obj.failCount = 0;
                //执行列表显示
                if (!obj.progressTimer) {
                    obj.displayProgress();
                }
            };
        } (this));
    };
    //文件选择按钮事件 将透明的文件输入框至于鼠标点击范围
    Upload.prototype.selectButtonMoveEvent = function (event) {
        var x = event.clientX + document.body.scrollLeft;;
        var y = event.clientY+ document.body.scrollTop;

        this.fileInput.style.top = y - 5 + "px";
        this.fileInput.style.left = x + 5 - this.fileInput.offsetWidth + "px";
    };
    //显示文件列表
    Upload.prototype.displayProgress = function (isNotRepeat) {
        var files = this.fileInput.files;
        var progressContainer = document.getElementById(this.config.fileProgressContainerId);
        var html;
        if (!this.listTemplate) {
            this.listTemplate = progressContainer.innerHTML;
        }
        if (!this.progressPercentage) {
            this.progressPercentage = new Array();
        }
        html = this.listTemplate;
        var dealHTML = "";
        for (var i = 0, len = files.length; i < len; i++) {
            if (!this.progressPercentage[i]) {
                this.progressPercentage[i] = this.config.waitingWord;
            }
            if (!checkFileType(this.config.fileTypes, files[i].name)) {
                this.progressPercentage[i] = this.config.fileTypeInvalidatedWord;
            }
            else if (!checkFileSize(this.config.fileSize, files[i].size)) {
                this.progressPercentage[i] = this.config.fileSizeInvalidatedWord;
            }
            var tempHTML = html.replace(/\{FileName\}/g, files[i].name);
            tempHTML = tempHTML.replace(/\{FileType\}/g, files[i].type);
            tempHTML = tempHTML.replace(/\{FileSize\}/g, getFileSizeString(files[i].size));
            tempHTML = tempHTML.replace(/\{UploadPercentage\}/g, this.progressPercentage[i]);
            dealHTML += tempHTML;
        }
        progressContainer.innerHTML = dealHTML;
        progressContainer.style.display = "";
        if (isNotRepeat) {
            return;
        }
        this.progressTimer = setTimeout(function (obj) {
            return function () {
                obj.displayProgress();
            };
        } (this)
        , 200);
    };
    //上传文件到服务器
    Upload.prototype.uploadFile = function (index) {
        var files = this.fileInput.files;
        var len = files.length;
        var fd = new FormData();
        var request = httpRequest();
        if (!index && index != 0) {
            index = 0;
        }
        //如果不是合法文件则跳过不上传
        if (this.progressPercentage[index] != this.config.waitingWord) {
            index++;
            this.failCount++;
            this.uploadFile(index);
        }
        else {
            fd.append("ling_file_name", files[index]);
            request.open("POST", this.config.url, true);
            request.onprogress = uploadProgressEvent(this, index);
            request.onreadystatechange = uploadSuccessEvent(this, index, request, len);
            request.onerror = uploadFailEvent(this, index);
            request.send(fd);
        }
    };
    
    //上传中的函数
    function uploadProgressEvent(obj, index) {
        return function (event) {
            obj.progressPercentage[index] = parseInt(event.loaded * 100 / event.total) + "%";
        };
    }
    //上成功函数
    function uploadSuccessEvent(obj, index, request, len) {
        return function () {
            if (request.readyState === 4 && request.status === 200) {
                if (request.responseText === "1") {
                    obj.progressPercentage[index] = "100%";
                    obj.successCount++;
                }
                else {
                    obj.progressPercentage[index] = obj.config.failWord;
                    obj.failCount++;
                }
                index++;
                if (index > len - 1) {
                    //结束时清除列表更新定时执行器 然后执行最后一遍
                    clearTimeout(obj.progressTimer);
                    obj.progressTimer = null;
                    obj.displayProgress(true);
                    if (obj.config.callback) {
                        obj.config.callback(len, obj.successCount, obj.failCount);
                    }
                    return;
                }
                obj.uploadFile(index);
            };
        }
    }
    //上传失败函数
    function uploadFailEvent(obj, index) {
        return function () {
            obj.progressPercentage[index] = obj.config.failWord;
            index++;
            obj.uploadFile(index);
        };
    }
    //动态绑定事件
    function addEvent(eventType, element, fn) {
        if (element && eventType && fn) {
            if (window.addEventListener) {
                element.addEventListener(eventType, fn);
            }
            else {
                element.attachEvent("on" + eventType, fn);
            }
        }
    };
    //获取XMLHttpRequest
    function httpRequest() {
        try {
            return new XMLHttpRequest();
        }
        catch (e) {
            return new ActiveXObject("Microsoft.XMLHTTP");
        }
    }
    //转换文件大小为k或者M表示
    function getFileSizeString(size) {
        if (!size && typeof (size) !== "number") {
            return "0k";
        }
        if (size > 1024 * 1024) {
            return (size / (1024 * 1024)).toFixed(2) + "M"
        }
        else {
            return (size / 1024).toFixed(2) + "k";
        }
    }
    //检查文件类型是否合法
    function checkFileType(allowFileTypes, fileName) {
        if (!allowFileTypes) {
            return true;
        }
        if (!fileName || fileName.indexOf('.') < 1) {
            return false;
        }
        var extension = fileName.substring(fileName.lastIndexOf('.'), fileName.length).toLowerCase();
        allowFileTypes = allowFileTypes.toLowerCase();
        if (allowFileTypes.indexOf("|" + extension + "|") > -1) {
            return true;
        }
        return false;
    }
    //检查文件大小是否合法
    function checkFileSize(allowSize, fileSize) {
        if (!allowSize || typeof (allowSize) != "number") {
            return true;
        }
        if (fileSize <= allowSize) {
            return true;
        }
        return false;
    }
    window.$ling = window.$ling || {};
    window.$ling.html5Upload = html5Upload;
    
})();

 

 

参考文章:http://blog.ncmem.com/wordpress/2023/12/25/html5实现文件批量上传组件/



标签:function,index,obj,上传,html5,return,文件批量,config
From: https://blog.51cto.com/u_14023400/9095631

相关文章

  • 使用HTML5实现多文件上传
    入门Fileinput之所以叫fileinput是因为它是一个标准的input元素,且其type属性被设置为"file"。很多年以来,fileinput一次只能选择并上传单个文件。在新的HTML5规范中为input元素添加了多选模式。当然,不同浏览器对于规范的实现一直以来都不尽相同。比如,Firefox3.6和WebKit以及Firef......
  • 文件上传以及出现的问题
    文件上传代码,可以直接去加入到工具类中去使用/** *通用上传请求(多个) */ @PostMapping("/uploads") publicAjaxResultuploadFiles(List<MultipartFile>files)throwsException{ try{ //上传文件路径 StringfilePath=YedSdkConfig.getUploadPath(); List......
  • 文件上传漏洞(四)edjpgcom
    简介edjpgcom是一个小工具,主要功能是在图片中插入一句话马或者小马,伪造的比较好。同时,edjpgcom还可以用于文件上传漏洞和文件包含漏洞的渗tou测试。需要注意的是,该软件仅供研究测试,严禁非法使用。edjpgcom是一个小工具,主要功能是在图片中插入一句话马或小马,从而实现伪造图片的目的......
  • TinyMCE富文本编辑器粘贴图片自动上传问题解决
    TinyMCE编辑器支持粘贴图片,但是自动会将图片转换成base64编码,这样将内容提交到后台,数据会很大。  图|TinyMCE本文内容配置TinyMCE(版本:5.10.0)向编辑器中粘贴图片自动上传到后台,以下为配置代码:tinymce.init({selector:'#textarea',plugins:'previewautolinkdire......
  • 前端学习笔记202311学习笔记第一百贰拾肆天-nodejs-登录鉴权-文件上传9
    ......
  • 前端歌谣-第柒拾叁课-node操作mongodb实现增删改查(图片上传功能)
    前言大家好我是歌谣今天继续给大家带来node操作mongodb实现增删改查实现上传功能环境准备后端mongodb数据库+node前端ejs模板安装处理文件的依赖npmimulter后端启动.\mongod--dbpath.\data\db后台运行连接数据库清空数据前端部分前端目录controller层constUserService=r......
  • 上传到东萍象棋网大师对局的UBB示例【重要提示:同一盘棋千万不要书写重复字段内容】
    [DhtmlXQ][DhtmlXQ_ver]www_dpxq_com[/DhtmlXQ_ver][DhtmlXQ_title]北京刘永富和北京左治[/DhtmlXQ_title][DhtmlXQ_event]鑫聚缘大奖赛[/DhtmlXQ_event][DhtmlXQ_date]2023/12/30[/DhtmlXQ_date][DhtmlXQ_init]800,600[/DhtmlXQ_init][DhtmlXQ_result]和局[/DhtmlXQ_......
  • 初识HTML5(2)
    在本文中,我将介绍HTML5的超链接标记和表格的相关标记。超链接标记超链接是HTML中非常重要的元素,它用于在不同网页或不同部分之间创建链接。以下是一些与超链接相关的标记和属性:使用<a>标签来定义超链接,其中href属性用于指定链接的目标URL,target属性用于指定链接如何打开。......
  • 初识HTML5
    HTML是一种超文本标记语言,用于创建和设计网页。HTML5是HTML的第五个版本,具有更丰富的功能和更好的效果。在开发过程中,我们可以使用Hbuilder作为开发工具,以及使用Chrome浏览器进行测试。HTML5的基本文档结构包括以下几个标签:<!DOCTYPEhtml>用于定义HTML5文档,<html>、<head>、<bod......
  • 记录--经常被cue大文件上传,忍不住试一下
    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助大文件上传主要步骤:获取文件对象,切分文件根据文件切片,计算文件唯一hash值上传文件切片,服务端保存起来合并文件切片,前端发送合并请求,服务端将文件切片合并为原始文件秒传,对于已经存在的分片,可以前端发个请求......