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

html5实现文件批量上传组件

时间:2023-12-25 18:33:59浏览次数:35  
标签: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%e5%ae%9e%e7%8e%b0%e6%96%87%e4%bb%b6%e6%89%b9%e9%87%8f%e4%b8%8a%e4%bc%a0%e7%bb%84%e4%bb%b6/

欢迎入群一起讨论

 

 

标签:function,index,obj,上传,html5,return,文件批量,config
From: https://www.cnblogs.com/songsu/p/17926738.html

相关文章

  • mysql 定时 数据库备份并上传到另一台服务器上,上传结束并删除源文件
    首先总共有两个脚本:#!/bin/bash:主要用于进行数据库备份、压缩、删除,单独运行命令是:bash XXX.sh#!/usr/bin/expect:主要用于进行数据备份文件的上传,单独运行命令是:expectXXX.sh这两个脚本都需要具有777权限:chmod777XXX.sh分成两个脚本写的原因是:expect主要是用于ssh远程......
  • HTML5文件上传操作
    一、File对象在HTML5出现之前,在Web上没有文件创建和复制,也没有文件处理,HTML5规范中包含3个文件相关的规范:“文件API”“文件API:目录和系统”以及“文件API:写入器”,文件API包含File对象、FileList对象和FileReader对象。为了保障客户端安全,大部分浏览器都未......
  • gitlab新建一个仓库,然后和本地代码关联,并上传本地代码到仓库中
    1.创建一个gitlab项目的仓库: 如果没有上传任何代码,这里Codetab会自动显示:从本地上传代码到仓库的操作命令:gitinitgitadd./gitcommit-m"firstcommit"gitbranch-Mmastergitremoteaddoriginhttps://oss.lalacorp.com/test-auttestapi/testforq.gitgitpush......
  • 一文掌握 Vue3 + Express 大文件分片上传、断点续传、秒传技巧!
    前言在日常开发中,文件上传是常见的操作之一。文件上传技术使得用户可以方便地将本地文件上传到Web服务器上,这在许多场景下都是必需的,比如网盘上传、头像上传等。但是当我们需要上传比较大的文件的时候,容易碰到以下问题:上传时间比较久;中间一旦出错就需要重新上传;一般服务端会对文件......
  • html5中怎么实现多文件上传功能
    本篇文章为大家展示了html5中怎么实现多文件上传功能,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。主要用到的是<input>的multiple属性代码如下:<inputtype="file"name="multipleFileUpload"multiple/>下面是页面的详细代码:代码......
  • HTML5 进阶系列:文件上传下载
    前言HTML5中提供的文件API在前端中有着丰富的应用,上传、下载、读取内容等在日常的交互中很常见。而且在各个浏览器的兼容也比较好,包括移动端,除了IE只支持IE10以上的版本。想要更好地掌握好操作文件的功能,先要熟悉每个API。FileList对象和file对象HTML中的input[type=......
  • html实现上传
    HTML实现上传在web应用程序中,上传文件是一个很常见的需求。在以前的传统web应用程序中,上传文件的实现要涉及到复杂的服务器端编程和各种扩展库的安装,给开发者带来很多麻烦。然而,现在随着HTML5技术的不断发展,基于浏览器的文件上传变得越来越简单。在本文中,我们将介绍如何使用HTML5......
  • 文件上传漏洞(三)Cknife
    Cknife是一款基于Python的渗tou测试工具,主要用于绕过Web应用程序中的安全防护机制,例如安全狗、360、云锁等。它可以通过自定义参数配置,生成各种不同的绕狗脚本,从而达到绕过安全防护的目的。Cknife具有使用简单、功能强大、支持多种编程语言等特点,是渗tou测试人员必备的工具之一。ck......
  • 如何通过蛋壳Uploader把ipa文件上传到App Store教程步骤
    在移动应用开发的过程中,将ipa文件上传至AppStore是非常关键的一环。对于那些没有Mac电脑的开发者来说,这一步骤可能会成为一个挑战。幸运的是,有一个名为“蛋壳Uploader”的在线工具,可以帮助开发者在没有Mac的情况下,轻松上传ipa文件到AppStore。一、准备工作在使用蛋壳Uploader......
  • 大文件分片上传
    文件传输是一个常见的需求。对于大文件的下载和上传,直接使用传统的方式可能会遇到性能和用户体验方面的问题。幸运的是,前端技术提供了一些高效的解决方案:文件流操作和切片下载与上传。本文将深入探讨这些技术,帮助你理解它们的原理和实现方法,以优化文件传输效率和提升用户体验。一......