Ajax 编程基础——FormData——视频上传(二)

2024-04-12 21:32

本文主要是介绍Ajax 编程基础——FormData——视频上传(二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

模板引擎

node.js 基础学习时就已经接触过模板引擎的概念,但那是为了在服务器端对数据和 HTML 结构进行拼接并响应给客户端。现在使用的是 ajax 技术,因此是需要在客户端对数据和模板进行拼接并直接更新在页面中。

原理是相同的原理,因此使用的步骤也大致相同。既然在服务器端使用的是 art-template 模板引擎,在客户端我们也选择这款模板引擎。因为它们的模板语法是一摸一样的,这就节省了再重新学习其他模板引擎的语法的时间精力。

1、art-template 官网 下载 art-template 模板引擎库文件并在 HTML 页面中引入库文件。

<script src="/js/template-web.js"></script>

2、准备 art-template 模板,art-template 模板是 html 文件中的一些代码片段,使用 script 标签包裹。使用 id 属性标识不同的模板,为了提高模板代码的可读性,可以为其设置 type 属性。

<script id="tpl" type="text/html"><div class="box"></div>
</script>

3、告诉模板引擎需要拼接哪个模板和数据

<script>var html = template('tpl', {userName: 'tkop', age: 18});
</script>

4、将拼接好的 html 字符串更新至页面中

// 将拼接好的字符串作为dom元素的内容
document.getElementById('container').innerHTML = html;

5、使用模板语法对数据和模板进行拼接操作

<script id="tpl" type="text/html"><div class="box">{{ userName }}</div>
</script>

有关 art-template 模板语法在 node.js 基础部分学习 express 框架时已经有所了解在此不重复笔记,笔记链接:Express 框架基础 。

FormData 对象

在我们需要发送的 ajax 请求需要携带大量的表单信息时, 逐个获取表单控件元素并将它们的值组合成需要的参数格式显然比较繁琐。前面学习过一个有关的表单方法 serializeArray() 可以方便我们获取表单控件中的数据,但是对于需求的实现还是不够理想。此时 ES6 中提供的 FormData 对象可以完美解决我们遇到的问题,但是 IE10 以下的浏览器不支持。

FormData 对象是一类用于模拟 HTML 表单,相当于将 HTML 表单映射成为表单对象(通过 js 使用键值对的形式表示表单控件的 name 和 value)。它自动将表单对象中的数据拼接成请求参数的格式。还具有异步上传二进制文件的功能。

FormData 对象的使用

1、准备 HTML 表单

<form id="form"><input type="text" name="username" /><input type="password" name="password" /><input type="button" />
</form>

不需要为表单设置请求方式和请求地址,也不需要提交按钮(当然可以设置一个 button 表单控件并为其绑定点击事件,点击后发送 ajax 请求提交表单),因为此时需要发送的是 ajax 请求。

2、将 HTML 表单转换为 formData 对象

利用表单元素和 FormData 构造函数创建表单对象。当然也可以创建一个空的表单对象,再根据需要使用表单对象的 set() 和 append() 方法为其添加数据。

var form = focument.getElementById('form');
var formData1 = new FormData(form);// 也可以创建空的表单对象、
var formData2 = new FormData();

3、提交表单对象

提交表单时 ajax 请求不需要设置请求头(FormData 自带请求头),所以不要存在为什么发送 ajax 请求前不去设置请求头信息的疑惑。例如以前我们发送请求前需要指明参数格式 xhr.setRequestHeader = '参数格式' ,现在不需要设置,直接发送即可。

xhr.send(formData1);

注意:

  • FormData 对象不能直接用于 get 请求,因为 get 请求方式的请求参数只能放在请求地址的后面,对象需要被传递到 send 方法中。
  • 服务器端 bodyParser 模块无法解析 formData 对象表单数据,我们需要使用 formidable 模块进行解析。
  • 在表单中并没有设置属性 enctype=“multipart/form-data” 来明确规定使用二进制形式表示表单数据,但是在后面可以直接进行二进制文件的上传功能和使用 formidable 模块解析。这说明 formData 对象在表示表单数据时使用的就是二进制形式。
  • 只有 bodyParser 模块在解析数据时需要配置以什么格式解析参数,使用 formData 模块不需要。这一点在以前的学习中没有去明确,现在补上。

在此明确一些题外知识:

  1. 表单传统方式提交时请求头信息中表示参数格式的字段内容为 Content-Type: application/x-www-form-urlencoded
  2. Formdate 对象自带的请求头信息中表示参数格式的字段内容为Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryxCZ0XYGrKJwqGsJw 。其数据在请求体中具体的形式与以前接触过的哪两种类型差异很大,如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EsA9CcN2-1618660512078)(https://z3.ax1x.com/2021/04/17/c5iGND.png)]

FormData 对象具有的方法

// 1、获取表单对象中属性的值formData.get('key');
formData1.get('name');
// 2、设置表单对象中的值formData.set('key', 'value');
formData1.set('name', '扬尘');
// 3、删除表单对象中属性的值formData.delete('key');
formData1.delete('age');
// 4、向表单对象中追加属性值formData.append('key', 'value');
formData1.append('hobbies', '敲代码');

注意:set 方法和 append 方法的区别是。在属性名已经存在的情况下,set 会覆盖已有的键名的值,append 会保留两个值(但是服务器使用的是最后的那个参数值)。

二进制文件上传

在利用 FormData 对象实现二进制文件上传功能前首先了解以下几个知识。

  1. 文件选择控件如果设置 multiple 属性是可以一次选择多个文件的,这些文件会保存在控件元素对象的 files 属性中。files 属性是保存文件的一个数组(无论用户选择几个文件)。

  2. ajax 请求对象 xhr 有一个 upload(上传)对象,上传相关的事件都会存储在这个对象中。

  3. 文件上传过程中会持续触发 upload 对象下的 progress(进度)事件,并且该事件的事件对象中存储了上传文件的总大小和已上传数据大小。事件对象的 total、loaded 属性分别保存了文件总大小和已上传数据的大小。

图片预览功能是在我们将图片上传至服务器后,服务器通常都会将图片地址作为响应数据传递到客户端。客户端可以从响应数据中获取图片地址,然后将图片显示在页面中(与前面还未上传前的预览不同)。未上传前的预览当时使用的是 js 内置的 FileReader 对象(存在兼容性问题)在客户端直接读取和显示图片。

<body><form action=""><input type="file" name="file" id="file" multiple><input type="button" value="上传" id="btn"><div id="prev"><!-- <video src="" muted="muted" autoplay="autoplay" loop="loop"></video> --></div><div class="progress" id="progress" style='display:none;'><div class="progress-bar" style="width: 0%;" id="progress-bar">0%</div></div></form>
</body><script>// 各dom元素的获取var file = document.getElementById('file');var btn = document.getElementById('btn');var progressBar = document.getElementById('progress-bar');var progress = document.getElementById('progress');var prev = document.getElementById('prev');// 上传按钮点击事件btn.onclick = function() {// 需要先将上次的上传预览清除掉prev.innerHTML = '';var xhr = new XMLHttpRequest();xhr.open('post', 'http://localhost:3000/formdata');// 创建表单对象并将各二进制文件追加至表单对象中var formdata = new FormData();for (let i = 0; i < file.files.length; i++) {// 这里的文件名称是自定义的formdata.append('video' + i, file.files[i]);}// 进度条功能实现xhr.upload.onprogress = function(e) {progress.style.display = 'block';var result = Math.round((e.loaded / e.total) * 100) + '%';progressBar.style.width = result;progressBar.innerHTML = result;}// 上传成功在获取到响应数据后预览文件(视频)xhr.onload = function() {if (xhr.status == 200) {var result = JSON.parse(xhr.responseText);// 已经上传完成可以将进度条隐藏progress.style.display = 'none';// 服务器端响应的数据 result={vide0path:'文件0路径', vide1path:'文件1路径', ...}for (var k in result) {var video = document.createElement('video');video.src = result[k];video.muted = "muted";video.autoplay = "autoplay";video.loop = "loop";prev.appendChild(video);}}}xhr.send(formdata);}
</script>

在这里插入图片描述如上图是上传多个文件(一个也一样)后在服务器端的 files 对象的内容,图中的内容可以帮我们捋清获取各个文件保存路径并响应给客户端的思路。

// 服务器端的代码
const express = require('express');
const formidable = require('formidable');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'public')));
// 实现文件上传的路由
app.post('/formdata', (req, res) => {const form = new formidable.IncomingForm();// 配置文件保存路径form.uploadDir = path.join(__dirname, 'public', 'upload');// 保留文件后缀名form.keepExtensions = true;form.parse(req, (err, fiels, files) => {var result = {};for (let k in files) {// 处理前端上传的文件的保存路径result[k + 'path'] = files[k].path.split('public')[1];}// 将路径信息响应给浏览器用于实现预览功能res.send(result);})
})

最后实现的结果如下:

在这里插入图片描述
可能你在自己实现进度条功能时由于文件太小或者网速太快导致进度条一下子就满了。为了更加确定进度条功能没有问题,可以将浏览器的网络状态设置为 slow 3G ,你会发现此时上传速度相当慢。

在这里插入图片描述

设置网络后上传文件(注意此时不能关闭开发者工具,不然浏览器的网络还是 No throttling )

在这里插入图片描述

这篇关于Ajax 编程基础——FormData——视频上传(二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/898292

相关文章

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

Go Playground 在线编程环境

For all examples in this and the next chapter, we will use Go Playground. Go Playground represents a web service that can run programs written in Go. It can be opened in a web browser using the follow

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念