HTML批量文件上传2——进度条显示

作者:私语茶馆

        非常多的云应用中需要上传文本,包括图片,文件等等,这些批量文件上传,往往涉及到进度条显示,多文件上传等,这里分享一个非常好的案例,来自BootStrapfriendly.com,方便大家开发产品时使用。

        已验证的场景:PHP+JavaScript; Servlet+JavaScript; 使用的环境:Tomcat

1.异步上传文件使用的基本概念

1.1.AJAX

进度条本质是用脚本控制ProgressBar的显示,其中会用到AJAX,AJAX有如下特征:

  • AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
  • AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
  • AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
  • AJAX 不需要任何浏览器插件,但需要用户允许 JavaScript 在浏览器上执行。
  • XMLHttpRequest 只是实现 Ajax 的一种方式。

1.2. Form

<form id="upload_form" enctype="multipart/form-data" method="post">

enctype=“multipart/form-data”: 指form中包含二进制的文件形式

1.3.XMLHttpRequest

        XMLHttpRequest(XHR)对象用于与服务器后端服务做请求交互,可以在不刷新页面的情况下请求特定的URL,获取数据。允许网元在不影响用户操作的情况下,更新页面的局部内容,是AJAX的一种关键使用绩效。

       XMLHttpRequest可以支持多种协议,包括FTP, file等。

        如果需要处理消息事件,可以使用EventSource,如果是全双工的可以是WebSocket。

参考:XMLHttpRequest - Web API | MDN (mozilla.org)

1.2.项目结构优化-独立的Scripts脚本

        从项目结构上讲,Script最好是独立文件,可以使用<script src="myscripts.js"></script>来引入,这样可以保持HTML简洁。

        如下图所示:

创建Scripts脚本

HTML引用该脚本

Script脚本

注意事项:要独立一个InitialLoad,并通过window.οnlοad=initialLoad来指定,如果脚本不起作用,可以检查一下windows.onload有没有设置。

2.异步批量上传文件及进度条案例

        这里前台部分直接使用Bootstrapfriedly.com的案例,后台用的是Apach的fileupload组件实现多文件上传,URL部分不同。

2.1. 前台界面

<div class="ath_container tile-container ">
    <div id="uploadStatus"></div>
    <h2 style="margin-bottom:10px">AJAX File Upload with Progress Bar using JavaScript</h2>
    <input type="file" id="fileUpload" multiple placeholder="choose file or browse" /> <!-- Add 'multiple' attribute for multiple file selection -->
    <br>
    <br>
    <button onclick="uploadFiles()">Upload</button> <!-- Change function name -->
    <div>
        <table id="progressBarsContainer">
            <!-- Table rows will be dynamically added here -->
        </table>
    </div> <!-- Container for progress bars -->
    <br>
</div>

说明点:

(1)这里没有直接使用Form,用button的Click来处理,后面在Script中使用AJAX的XMLHttpRequest提交表单。

(2)table id=progressBarsContainer做为占位符号,后续ajax发送请求后,用于增量显示图片文件状态用。

2.2. CSS风格文件

* {
    margin: 0px;
    padding: 0px;
    box-sizing: border-box;
}



body {
    font-family: -apple-system, BlinkMacSystemFont, Roboto, Segoe UI,
        Helvetica Neue, Helvetica, Arial, sans-serif;
    margin: 0 auto;
    -webkit-font-smoothing: antialiased;
    box-sizing: border-box;
    color: 
#2f2f2f;
    line-height: 1.5;
}

.ath_container {
    width: 740px;
    margin: 20px auto;
    padding: 0px 20px 0px 20px;
}

.ath_container {
    width: 820px;
    border: 
#d7d7d7 1px solid;
    border-radius: 5px;
    padding: 10px 20px 10px 20px;
    box-shadow: 0 0 5px 
rgba(0, 0, 0, .3);
    /* border-radius: 5px; */
}

#uploadStatus {
    color: 
#00e200;
}

.ath_container a {
    text-decoration: none;
    color: 
#2f20d1;
}

.ath_container a:hover {
    text-decoration: underline;
}

.ath_container img {
    height: auto;
    max-width: 100%;
    vertical-align: middle;
}


.ath_container .label {
    color: 
#565656;
    margin-bottom: 2px;
}



.ath_container .message {
    padding: 6px 20px;
    font-size: 1em;
    color: 
rgb(40, 40, 40);
    box-sizing: border-box;
    margin: 0px;
    border-radius: 3px;
    width: 100%;
    overflow: auto;
}

.ath_container .error {
    padding: 6px 20px;
    border-radius: 3px;
    background-color: 
#ffe7e7;
    border: 1px solid 
#e46b66;
    color: 
#dc0d24;
}

.ath_container .success {
    background-color: 
#48e0a4;
    border: 
#40cc94 1px solid;
    border-radius: 3px;
    color: 
#105b3d;
}

.ath_container .validation-message {
    color: 
#e20900;
}

.ath_container .font-bold {
    font-weight: bold;
}

.ath_container .display-none {
    display: none;
}

.ath_container .inline-block {
    display: inline-block;
}

.ath_container .float-right {
    float: right;
}

.ath_container .float-left {
    float: left;
}

.ath_container .text-center {
    text-align: center;
}

.ath_container .text-left {
    text-align: left;
}

.ath_container .text-right {
    text-align: right;
}

.ath_container .full-width {
    width: 100%;
}

.ath_container .cursor-pointer {
    cursor: pointer;
}

.ath_container .mr-20 {
    margin-right: 20px;
}

.ath_container .m-20 {
    margin: 20px;
}



.ath_container table {
    border-collapse: collapse;
    border-spacing: 0;
    width: 100%;
    border: 1px solid 
#ddd;
    margin-top: 20px;
}


.ath_container table th,
.ath_container table td {
    text-align: left;
    padding: 5px;
    border: 1px solid 
#ededed;
    width: 50%;
}

tr:nth-child(even) {
    background-color: 
#f2f2f2
}

.ath_container .progress {
    margin: 20px 0 0 0;
    width: 300px;
    border: 1px solid 
#ddd;
    padding: 5px;
    border-radius: 5px;
}

.ath_container .progress-bar {
    width: 0%;
    height: 24px;
    background-color: 
#4CAF50;
    margin-top: 15px;
    border-radius: 12px;
    text-align: center;
    color: 
#fff;
}

@media all and (max-width: 780px) {
    .ath_container {
        width: auto;
    }
}


.ath_container input,
.ath_container textarea,
.ath_container select {
    box-sizing: border-box;
    width: 200px;
    height: initial;
    padding: 8px 5px;
    border: 1px solid 
#9a9a9a;
    border-radius: 4px;
}

.ath_container input[type="checkbox"] {
    width: auto;
    vertical-align: text-bottom;
}

.ath_container textarea {
    width: 300px;
}

.ath_container select {
    display: initial;
    height: 30px;
    padding: 2px 5px;
}

.ath_container button,
.ath_container input[type=submit],
.ath_container input[type=button] {
    padding: 8px 30px;
    font-size: 1em;
    cursor: pointer;
    border-radius: 25px;
    color: 
#ffffff;
    background-color: 
#6213d3;
    border-color: 
#9554f1 
#9172bd 
#4907a9;
}

.ath_container input[type=submit]:hover {
    background-color: 
#f7c027;
}

::placeholder {
    color: 
#bdbfc4;
}

.ath_container label {
    display: block;
    color: 
#565656;
}

@media all and (max-width: 400px) {
    .ath_container {
        padding: 0px 20px;
    }

    .ath_container {
        width: auto;
    }

    .ath_container input,
    .ath_container textarea,
    .ath_container select {
        width: 100%;
    }
}

2.3. JavaScript脚本

    function uploadFiles() {
        var fileInput = document.getElementById('fileUpload');
        var files = fileInput.files;

        //(1)校验图片文件,并上传
        for (var i = 0; i < files.length; i++) {
            var allowedExtensions = ['.jpg', '.jpeg', '.png', '.pdf', '.svg', '.zip', '.docx', '.xlsx'];
            var fileExtension = files[i].name.substring(files[i].name.lastIndexOf('.')).toLowerCase();

            if (allowedExtensions.includes(fileExtension)) {
                //(1.1)一次上传一个文件,并显示文件名和进度
                uploadFile(files[i]);
            } else {
                alert('Invalid file type: ' + fileExtension);
            }
        }
    }

    function uploadFile(file) {
        var formData = new FormData();
        formData.append('file', file);

        var progressBarContainer = document.createElement('div'); // Container for progress bar and file name
        progressBarContainer.className = 'progress-container';

        var fileName = document.createElement('div'); // Display file name
        fileName.className = 'file-name';
        fileName.textContent = file.name;
        //progressBarContainer.appendChild(fileName);

        var progressBar = document.createElement('div'); // Create a new progress bar element
        progressBar.className = 'progress-bar';
        progressBar.id = 'progressBar_' + file.name;

        progressBarContainer.appendChild(progressBar);

        var progressBarsContainer = document.getElementById('progressBarsContainer');

        var newRow = document.createElement('tr'); // Create a new table row
        var newCell = document.createElement('td'); // Create a new table cell
        var newCell2 = document.createElement('td'); // Create a new table cell
        newCell.appendChild(fileName);
        newCell2.appendChild(progressBarContainer);
        newRow.appendChild(newCell);
        newRow.appendChild(newCell2);
        progressBarsContainer.appendChild(newRow);

        var xhr = new XMLHttpRequest();

        xhr.upload.addEventListener('progress', function(event) {
            if (event.lengthComputable) {
                var percent = Math.round((event.loaded / event.total) * 100);
                progressBar.style.width = percent + '%';
                progressBar.innerHTML = percent + '%';
            }
        });

        xhr.addEventListener('load', function(event) {
            var uploadStatus = document.getElementById('uploadStatus');
            uploadStatus.innerHTML = event.target.responseText;
            // Reset the input field of type "file"
            document.getElementById('fileUpload').value = '';

        });

        xhr.open('POST', 'upload.do', true);
        xhr.send(formData);
    }

关键点:

  • 这里的文件上传是一个一个上传的,上传一个显示一个状态,上传完成后,显示全部文件的状态。
  • xhr.open('post', 'upload.do',true); URL需要看本身后台发布的URL,我这里测试的是一个Servlet后台。

3.效果图

        上传前

上传后

4.相关章节

HTML批量文件上传1——图像预览方式_html上传多张图片并预览-CSDN博客

完整的项目下载(待后续补充):

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/605265.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

kubernetes附加组件—图形化管理工具Dashboard

一、介绍 Dashboard是k8s集群管理的一个WebUi&#xff0c;它是k8s的一个附加组件&#xff0c;需要单独部署。 我们可以通过图形化的方法&#xff0c;创建、删除、修改、查询k8s资源。 二、安装部署dashboard组件 Github地址&#xff1a;GitHub - kubernetes/dashboard: Gen…

物联网实战--平台篇之(四)账户后台交互

目录 一、交互逻辑 二、请求验证码 三、帐号注册 四、帐号/验证码登录 五、重置密码 本项目的交流QQ群:701889554 物联网实战--入门篇https://blog.csdn.net/ypp240124016/category_12609773.html 物联网实战--驱动篇https://blog.csdn.net/ypp240124016/category_12631…

自动驾驶中常见坐标系极其转换

各个传感器坐标系 相机坐标系统 摄像头的作用是把三维世界中的形状、颜色信息,压缩到一张二维图像上。基于摄像头的感知算法则是从二维图像中提取并还原三维世界中的元素和信息,如车道线,车辆、行人等,并计算他们与自己的相对位置。 感知算法和相机相关的坐标系有图像坐…

javaWeb入门(自用)

1. vue学习 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script src"https://unpkg.com/vue2"></script> </head> <body><div id"…

大语言模型入门介绍(附赠书)

自2022年底ChatGPT的震撼上线以来&#xff0c;大语言模型技术迅速在学术界和工业界引起了广泛关注&#xff0c;标志着人工智能技术的又一次重要跃进。作为当前人工智能领域的前沿技术之一&#xff0c;代表了机器学习模型在规模和复杂性上的显著进步。它们通常由深度神经网络构成…

解决微信小程序电脑能正常使用,手机端无法正常访问的SSL证书问题

目录 前言1 问题描述与调试2 探索问题根源2.1 用户反馈收集2.2 尝试手机端访问2.3 PC端调试 3 确认问题与解决方案3.1 检查SSL证书3.2 重新部署SSL证书3.3 测试修复效果 4 SSL&#xff08;Secure Sockets Layer&#xff09;证书中间证书4.1 SSL证书链的构成4.2 中间证书的作用 …

MindSponge分子动力学模拟——定义一个分子系统

技术背景 在前面两篇文章中&#xff0c;我们分别介绍了分子动力学模拟软件MindSponge的软件架构和安装与使用。这里我们进入到实用化阶段&#xff0c;假定大家都已经在本地部署好了基于MindSpore的MindSponge的编程环境&#xff0c;开始用MindSponge去做一些真正的分子模拟的工…

04、Kafka集群安装

03、Kafka 集群安装 1、准备工作 首先准备一台虚拟机&#xff0c;centos7系统&#xff0c;先在一台上配置安装后&#xff0c;最后克隆成多台机器。 1.1 安装JDK &#xff08;1&#xff09;下载JDK&#xff0c;上传到 /root/software 路径 下载地址&#xff1a;https://www…

DELL EMC unity存储系统如何初始化

在客户的存储使用过程中&#xff0c;经常会碰到一些场景需要对存储系统做重新初始化&#xff0c;就是回到出厂时候的配置。比如&#xff0c;客户设备要利旧&#xff0c;二次使用&#xff0c;一般都要回到出厂状态做重新配置的动作。存储严重故障&#xff0c;没有能力修复或者数…

现货黄金今日行情分析:昨日高低点法

进行交易之前&#xff0c;投资者要对现货黄金今日行情进行一波分析&#xff0c;我们交易决策应该建立在合理分析的基础之上。那么打开市场交易软件看到现货黄金今日行情之后&#xff0c;该如何着手进行分析呢&#xff1f;下面我们就来讨论一下具体的方法。 要进行现货黄金今日行…

【QuikGraph】C#调用第三方库实现迪杰斯特拉(Dijkstra)算法功能

QuikGraph库介绍 项目地址&#xff1a;https://github.com/KeRNeLith/QuikGraph QuikGraph为.NET提供了通用的有向/无向图数据结构和算法。 QuikGraph提供了深度优先搜索、广度优先搜索、A*搜索、最短路径、k最短路径&#xff0c;最大流量、最小生成树等算法。 QuikGraph最初…

大模型的不足与解决方案

文章目录 ⭐ 不具备记忆能力 上下文窗口受限⭐ 实时信息更新慢 新旧知识难区分⭐ 内部操作很灵活 外部系统难操作⭐ 无法为专业问题 提供靠谱的答案⭐ 解决方案的结果 各有不同的侧重 在前面三个章节呢&#xff0c;为大家从技术的角度介绍了大模型的历程与发展&#xff0c;也为…

Jenkins +git +web(vue) centos8.5 实战打包部署 运维系列二

1新建一个工程 #cat qy.sh #!/bin/bash cd /data/.jenkins/workspace/web rm -rf dist/ rm -rf qysupweb.tar.gz npm run build tar -czvf qysupweb.tar.gz dist/ #点击构建

STM32学习计划

前言&#xff1a; 这里先记录下STM32的学习计划。 2024/05/08 今天我正在学习的是正点原子的I.MX6ULL APLHA/Mini 开发板的 Linux 之ARM裸机第二期开发的视频教程&#xff0c;会用正点原子的I.MX6ULL开发板学习第二期ARM裸机开发的教程&#xff0c;然后是学习完正点原子的I.M…

python数据分析——pandas DataFrame基础知识1

参考资料&#xff1a;活用pandas库 1、加载数据集 通常调用read_csv函数来加载CSV数据文件。若是.tsv文件也是用read_csv函数。 # 导入库 import pandas as pd # 默认情况下&#xff0c;read_csv函数会读取逗号分隔文件 # Gapminder数据使用制表符分隔 # 可以吧sep参数设置为…

【网络协议】----IPv6协议报文、地址分类

【网络协议】----IPv6协议简介 【网络协议】----IPv6协议简介IPv6特点IPv4 和 IPv6报文结构IPv6报文格式-拓展报头 IPv6地址分类IPv6地址表示IPv6单播地址可聚合全球单播地址链路本地地址唯一本地地址特殊地址补充 接口标识&#xff08;主机位&#xff09;生成方法通过EUI-64规…

网络层协议之 IP 协议

IP 协议格式 4 位版本&#xff1a;此处的取值只有两个&#xff0c;4&#xff08;IPv4&#xff09;和 6&#xff08;IPv6&#xff09;&#xff0c;即指定 IP 协议的版本。 4 位首部长度&#xff1a;描述了 IP 报头多长&#xff0c;IP 报头是变长的&#xff0c;因为报头中的选项部…

信息系统项目管理师0094:项目管理过程组(6项目管理概论—6.4价值驱动的项目管理知识体系—6.4.3项目管理过程组)

点击查看专栏目录 文章目录 6.4.3项目管理过程组1.适应型项目中的过程组2.适应型项目中过程组之间的关系6.4.3项目管理过程组 项目管理过程组是为了达成项目的特定目标,对项目管理过程进行的逻辑上的分组。项目管理过程组不同于项目阶段:①项目管理过程组是为了管理项目,针对…

WebRTC 采集音视频数据

WebRTC 采集音视频数据 WebRTC 采集音视频数据getUserMedia API 简介浏览器兼容性getUserMedia 接口格式MediaStreamConstraintsMediaTrackConstraints 采集音频数据MediaStream 和 MediaStreamTrack本地视频预览切换摄像头显示参考 WebRTC 采集音视频数据 getUserMedia API 简…

C语言 | Leetcode C语言题解之第77题组合

题目&#xff1a; 题解&#xff1a; int** combine(int n, int k, int* returnSize, int** returnColumnSizes) {int* temp malloc(sizeof(int) * (k 1));int tempSize 0;int** ans malloc(sizeof(int*) * 200001);int ansSize 0;// 初始化// 将 temp 中 [0, k - 1] 每个…