头像预览和上传

article/2025/7/2 14:54:34

        在写一个项目的时候,遇到了头像修改这个功能的需求,在最开始的学习中发现可以通过type为file的input文件读取图片,然后将其转换为DataUrl格式,最终作为Ima元素的src即可在页面上展示图片。但到后面开始写交互的时候发现DataUrl格式的图片数据太长了,发送请求不是请求头太大就是数据库塞不下,然后开始学习后面的multipart/form-data这种数据传输方式(虽然没用,但学了doge^-^)

前端开发中的 DataUrl:原理、应用与实践

        一、DataUrl 是什么

        DataUrl,即数据 URL,是一种将数据直接嵌入 URL 的方式,其目的是将一些小的数据,直接嵌入到网页中,从而避免额外的网络请求。它的格式遵循特定的规范,基本格式如下:

data:[<mediatype>][;base64],<data>

        其中,mediatype是数据的 MIME 类型,例如image/png表示 PNG 图片,text/plain表示纯文本等;base64是一个可选的参数,当数据需要进行 Base64 编码时使用,一般图片等二进制数据会采用 Base64 编码;最后的<data>部分就是实际的数据内容。

举个简单的例子,一个表示绿色像素点的 DataUrl 如下:

 

data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7

        在这个 DataUrl 中,image/gif表明数据是 GIF 图片类型,base64表示后面的数据经过了 Base64 编码,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7就是编码后的图片数据。

        二、DataUrl 的原理

          DataUrl 的实现原理基于浏览器对 URL 协议的支持和解析。当浏览器遇到一个 DataUrl 时,它会按照上述格式规则对其进行解析,提取出 MIME 类型和数据部分。如果数据是经过 Base64 编码的,浏览器会自动对其进行解码,然后根据 MIME 类型来处理数据。

        以图片为例,当一个 HTML 页面中使用 DataUrl 作为img标签的src属性值时,浏览器解析到该 DataUrl 后,会解码数据并将其渲染为图片,整个过程不需要发起额外的网络请求去获取图片资源。这种方式对于一些小的、不经常变化的资源来说,能够有效减少网络请求次数,提升页面的加载速度。

        三、常见使用场景

(一)小图标嵌入

        在网页设计中,常常会用到一些小图标,如按钮图标、导航图标等。将这些小图标转换为 DataUrl,然后直接嵌入到 CSS 或 HTML 中,可以避免为每个小图标单独发起网络请求。例如,在 CSS 中设置背景图片:

 

.icon {

background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...);

}

        这样,当页面加载时,图标会随着 CSS 样式的解析一起呈现,无需额外请求,提高了页面渲染效率。

(二)内联样式和脚本

对于一些简单的 CSS 样式或 JavaScript 脚本,也可以使用 DataUrl 的形式嵌入到 HTML 中。比如,在 HTML 的style标签中嵌入一段 Base64 编码后的 CSS 样式:

 
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><style>body {background: url(data:text/css;base64,LmltZyB7cGFkZGluZzogMTAwcHggMTAwcHg7fQ==);}</style><title>DataUrl示例</title></head><body><!-- 页面内容 --></body></html>

        虽然这种方式在实际项目中不常大规模使用,但在某些特定场景下,如生成动态页面且样式内容较小时,能简化资源管理。

        四、优缺点分析

(一)优点

  1. 减少网络请求:正如前面提到的,将小资源转换为 DataUrl 嵌入页面,避免了额外的 HTTP 请求,对于页面加载速度有显著提升,尤其是在网络环境较差的情况下效果更明显。
  1. 便于资源管理:将资源直接嵌入代码中,不需要单独管理资源文件,在一些小型项目或特定场景下,能简化项目结构和开发流程。
  1. 动态生成资源:可以根据运行时的数据动态生成 DataUrl,实现一些灵活的功能,如根据用户输入生成特定的图片或下载文件。

(二)缺点

  1. 增大文件体积:Base64 编码会使数据体积增加约 1/3 左右,对于较大的资源,转换为 DataUrl 后会使 HTML 或 CSS 文件体积大幅增大,反而影响加载速度,这同时也意味着其不太适合作为请求的数据发送。
  1. 缓存问题:由于 DataUrl 直接嵌入在代码中,浏览器无法像对独立资源文件那样进行有效的缓存管理。如果 DataUrl 中的数据经常变化,会导致每次页面加载都需要重新处理这部分数据。
  1. 可读性和可维护性差:大量的 Base64 编码数据嵌入代码中,会使代码变得冗长且难以阅读和维护,不利于项目的长期迭代和团队协作。

五、FileReader 对象与 DataUrl

        FileReader是 JavaScript 中用于异步读取文件内容的对象,常与DataUrl结合使用,实现将本地文件转换为DataUrl,从而在前端进行处理和展示。

(一)基本用法

FileReader对象有几个重要的方法和事件:

  • readAsDataURL(file):读取指定的文件,并将文件内容以 DataUrl 的形式返回。
  • onload事件:当文件读取成功完成时触发,在该事件回调函数中可以获取到转换后的 DataUrl。
  • onerror事件:当文件读取发生错误时触发。

        以下是一个简单示例,演示如何使用FileReader将用户选择的图片文件转换为 DataUrl 并展示在页面上:

 
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>FileReader与DataUrl示例</title></head><body><input type="file" id="fileInput"><img id="previewImage" src="" alt="图片预览"><script>const fileInput = document.getElementById('fileInput');const previewImage = document.getElementById('previewImage');fileInput.addEventListener('change', function (e) {const file = e.target.files[0];if (file) {const reader = new FileReader();reader.onload = function (event) {const dataUrl = event.target.result;previewImage.src = dataUrl;};reader.onerror = function (error) {console.log('文件读取错误: ', error);};reader.readAsDataURL(file);}});</script></body></html>

        在上述代码中,当用户选择一个图片文件后,通过FileReader的readAsDataURL方法将文件读取为 DataUrl,读取成功后在onload事件中,将得到的 DataUrl 设置为img标签的src属性,从而实现图片的预览功能。

(二)实际应用场景拓展

        在实际项目中,FileReader与DataUrl结合可以应用于更多场景。例如,在图片上传功能中,在将图片发送到服务器之前,可以先使用FileReader将图片转换为 DataUrl 进行本地预览,确认无误后再上传,提升用户体验。还可以在一些表单提交场景中,将用户上传的文件转换为 DataUrl 格式,与其他表单数据一起以 JSON 格式发送到服务器,简化数据传输和处理流程。

六、multipart/form-data

(一)原理

        multipart/form-data是一种在 HTTP 协议中用于发送表单数据的编码方式,特别是在需要上传文件的场景中广泛应用。它将表单数据分割成多个部分,每个部分都有自己的头部信息,描述了数据的类型、名称等信息,各部分之间使用特定的边界字符串进行分隔。服务器接收到数据后,根据边界字符串解析出各个部分的数据,并进行相应的处理 。

例如,当用户在网页上提交一个包含文件和文本字段的表单时,浏览器会按照multipart/form-data的格式将数据封装成类似以下的结构发送给服务器:

 

--boundary

Content-Disposition: form-data; name="username"

JohnDoe

--boundary

Content-Disposition: form-data; name="userfile"; filename="example.txt"

Content-Type: text/plain

这是文件的内容

--boundary--

其中,boundary是自定义的边界字符串,用于区分不同的数据部分。

(二)使用场景

  1. 文件上传:最常见的应用场景就是文件上传,无论是单个文件还是多个文件上传,multipart/form-data都能很好地处理文件数据与其他表单数据(如文件名、文件描述等文本字段)的混合传输。
  1. 表单提交含二进制数据:当表单中除了普通文本数据,还包含图片、音频、视频等二进制数据时,multipart/form-data是理想的选择,能确保各类数据准确无误地发送到服务器。

(三)与 DataUrl、FileReader 的对比

  1. 数据传输方式
    • DataUrl:将数据直接嵌入 URL 中,适用于小数据的内联展示或简单的数据导出,数据会随着 HTML、CSS 等页面代码一起传输。
    • FileReader:主要用于在前端将本地文件读取为特定格式(如 DataUrl),方便在前端进行数据处理和展示,本身不涉及数据向服务器的传输。
    • multipart/form-data:专门用于在 HTTP 请求中将表单数据(包括文件和普通数据)发送到服务器,是一种数据传输协议。
  1. 适用场景
    • DataUrl:适合小图标嵌入、内联样式脚本、小型数据导出等场景。
    • FileReader:常用于需要在前端对本地文件进行处理,如预览图片等场景。
    • multipart/form-data:主要用于文件上传以及包含二进制数据的表单提交。
  1. 优缺点
    • DataUrl:优点是减少网络请求、便于资源管理;缺点是增大文件体积、缓存困难、可读性差。
    • FileReader:优点是方便前端处理本地文件;缺点是仅适用于前端操作,不涉及数据传输到服务器。
    • multipart/form-data:优点是能高效传输复杂表单数据,支持文件上传;缺点是数据格式相对复杂,解析处理需要一定开销。

(四)示例

以下是一个使用multipart/form-data进行文件上传的 HTML 表单示例:

 
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>multipart/form-data示例</title></head><body><form action="upload.php" method="post" enctype="multipart/form-data"><label for="username">用户名:</label><input type="text" id="username" name="username" required><br><label for="userfile">选择文件:</label><input type="file" id="userfile" name="userfile" required><br><input type="submit" value="上传"></form></body></html>

        在上述代码中,通过设置表单的enctype="multipart/form-data"属性,指定了使用multipart/form-data编码方式发送表单数据。服务器端(如upload.php)可以根据这种编码格式解析接收到的数据,提取出用户名和上传的文件。

        七、multipart/form-data在js里面的使用:Form-data

(一)原理

    FormData是HTML5新增的一个接口,用于创建和操作表单数据。它提供了一种简单的方式来收集表单元素的数据,并将其格式化为multipart/form-dataapplication/x-www-form-urlencoded格式,以便通过AJAX请求发送到服务器。

    FormData对象的核心原理是模拟HTML表单的提交过程,将表单中的各个字段(包括文本字段、文件字段等)收集起来,并按照一定的格式组织成键值对。这些键值对可以包含普通文本数据,也可以包含文件对象,然后可以通过XMLHttpRequest或Fetch API发送到服务器。

(二)常用方法与属性

  1. 构造函数

    • new FormData():创建一个空的FormData对象。
    • new FormData(form):从一个HTML表单元素中收集数据,创建FormData对象。
  2. 方法

    • append(name, value):向FormData中添加一个字段,字段名为name,值为value
    • append(name, file, filename):向FormData中添加一个文件字段,file是一个File对象,filename是可选的文件名。
    • delete(name):从FormData中删除所有字段名为name的字段。
    • get(name):获取FormData中第一个字段名为name的字段的值。
    • getAll(name):获取FormData中所有字段名为name的字段的值,返回一个数组。
    • has(name):检查FormData中是否存在字段名为name的字段。
    • set(name, value):设置FormData中字段名为name的字段的值,如果该字段不存在则添加。
    • set(name, file, filename):设置FormData中字段名为name的文件字段的值。
    • entries():返回一个迭代器,用于遍历FormData中的所有键值对。
    • keys():返回一个迭代器,用于遍历FormData中的所有字段名。
    • values():返回一个迭代器,用于遍历FormData中的所有字段值。

(三)应用场景

  1. AJAX表单提交:通过FormData可以方便地将表单数据通过AJAX请求发送到服务器,而不需要手动序列化表单数据。
  2. 文件上传FormData可以轻松处理文件上传,将文件对象添加到FormData中,然后通过AJAX请求发送到服务器。
  3. 动态表单数据处理:在一些需要动态添加或修改表单数据的场景中,FormData提供了灵活的API来操作表单数据。

(四)与其他技术的对比

  1. 与传统表单提交对比

    • 传统表单提交:表单数据会直接提交到服务器,页面会刷新。
    • FormData+AJAX:可以在不刷新页面的情况下异步提交表单数据,提升用户体验。
  2. 与手动序列化表单数据对比

    • 手动序列化:需要自己编写代码将表单数据转换为字符串格式,处理文件上传时比较复杂。
    • FormData:自动处理表单数据的格式,包括文件上传,简化了开发过程。
  3. 与DataUrl对比

    • DataUrl:适合将小数据嵌入到URL中,用于内联展示或简单数据导出。
    • FormData:适合处理复杂的表单数据,尤其是包含文件的表单数据,并将其发送到服务器。

(五)示例

以下是几个使用FormData的示例:

1. 从HTML表单创建FormData并提交

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>FormData示例1</title><!-- 引入jQuery --><script src="https://cdn.tailwindcss.com"></script>
</head><body><form id="myForm"><input type="text" name="username" value="John"><input type="email" name="email" value="john@example.com"><input type="file" name="avatar"><button type="button" id="submitBtn">提交</button></form><script>const form = document.getElementById('myForm');const submitBtn = document.getElementById('submitBtn');submitBtn.addEventListener('click', function() {const formData = new FormData(form);$.ajax({url: '/submit',type: 'POST',data: formData,processData: false,  // 不处理数据contentType: false,  // 不设置内容类型success: function(response) {console.log(response);},error: function(error) {console.error('Error:', error);}});});</script>
</body></html>
2. 动态创建FormData并添加数据
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>FormData示例2</title><!-- 引入jQuery --><script src="https://cdn.tailwindcss.com"></script>
</head><body><input type="text" id="username" value="Alice"><input type="file" id="fileInput"><button type="button" id="submitBtn">提交</button><script>const usernameInput = document.getElementById('username');const fileInput = document.getElementById('fileInput');const submitBtn = document.getElementById('submitBtn');submitBtn.addEventListener('click', function() {const formData = new FormData();// 添加文本字段formData.append('username', usernameInput.value);// 添加文件字段if (fileInput.files.length > 0) {formData.append('file', fileInput.files[0]);}// 添加额外的数据formData.append('timestamp', new Date().toISOString());$.ajax({url: '/upload',type: 'POST',data: formData,processData: false,  // 不处理数据contentType: false,  // 不设置内容类型success: function(response) {console.log(response);},error: function(error) {console.error('Error:', error);}});});</script>
</body></html>
3. 结合FileReader和FormData实现图片预览和上传

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>FormData示例3</title><!-- 引入jQuery --><script src="https://cdn.tailwindcss.com"></script>
</head><body><input type="file" id="imageInput" accept="image/*"><img id="preview" src="" alt="图片预览" style="max-width: 300px;"><button type="button" id="uploadBtn">上传图片</button><script>const imageInput = document.getElementById('imageInput');const preview = document.getElementById('preview');const uploadBtn = document.getElementById('uploadBtn');let selectedFile = null;imageInput.addEventListener('change', function() {if (this.files.length > 0) {selectedFile = this.files[0];// 使用FileReader预览图片const reader = new FileReader();reader.onload = function(e) {preview.src = e.target.result;};reader.readAsDataURL(selectedFile);}});uploadBtn.addEventListener('click', function() {if (!selectedFile) {alert('请先选择图片');return;}const formData = new FormData();formData.append('image', selectedFile);$.ajax({url: '/upload-image',type: 'POST',data: formData,processData: false,  // 不处理数据contentType: false,  // 不设置内容类型success: function(response) {console.log('上传成功:', response);alert('图片上传成功');},error: function(error) {console.error('上传失败:', error);alert('图片上传失败');}});});</script>
</body></html>


头像的修改的话把修改img的src步骤放到请求成功的回调函数里面

        最后本周感悟(也是本月doge//_\\),这段时间做那个新闻资讯类的项目收获很多,但缺点也暴露了出来,代码格式问题不是很大,但复用部分做的不咋滴,这点要改善一下。下一个学习计划已经发下来了,node.js的学习我一定会加倍努力的\*—*/


http://www.hkcw.cn/article/ODdcHqrGfx.shtml

相关文章

解锁效率新高度:Agent Zero智能助手框架

探索Agent Zero AI框架&#xff1a;您的个性化智能助手 在迅速发展的科技世界&#xff0c;Agent Zero AI框架为我们揭开了一个全新的大门。被设计成能够与用户同步成长与学习的智能助手&#xff0c;Agent Zero展现了它作为个性化使用工具的非凡潜力。在本篇文章中&#xff0c;…

第43节:Vision Transformer (ViT)视觉领域的革命性架构

1. ViT的诞生背景与核心思想 Vision Transformer (ViT) 是2020年由Google Research团队提出的一种革命性计算机视觉架构,它将自然语言处理(NLP)领域中大获成功的Transformer模型引入到计算机视觉任务中。这一创新彻底改变了传统卷积神经网络(CNN)在视觉任务中的主导地位,为图…

leetcode0513. 找树左下角的值-meidum

1 题目&#xff1a;找树左下角的值 官方标定难度&#xff1a;中 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: 输入: root [2,1,3] 输出: 1 示例 2: 输入: [1,2,3,4,null,5,6,null,null,7]…

从webshell管理工具(蚁剑 冰蝎 哥斯拉 菜刀 哥斯拉等)程控制主机后,再将这个控制能力上线到MSF 为什么要这么做了?一篇文章告诉你

目录 一、为什么Webshell管理工具需要上线到Metasploit&#xff1f; 什么情况下需要上线到Metasploit&#xff1f; 二、常见Webshell管理工具及上线Metasploit的步骤 1. 蚁剑&#xff08;AntSword&#xff09;上线到Metasploit 上线步骤&#xff1a; 实际案例&#xff1a…

【Ragflow】24.Ragflow-plus开发日志:增加分词逻辑,修复关键词检索失效问题

概述 在RagflowPlus v0.3.0 版本推出之后&#xff0c;反馈比较多的问题是&#xff1a;检索时&#xff0c;召回块显著变少了。 如上图所示&#xff0c;进行检索测试时&#xff0c;关键词相似度得分为0&#xff0c;导致混合相似度(加权相加得到)也被大幅拉低&#xff0c;低于设定…

YOLOv5 :训练自己的数据集

- **&#x1f368; 本文为[&#x1f517;365天深度学习训练营](https://mp.weixin.qq.com/s/rnFa-IeY93EpjVu0yzzjkw) 中的学习记录博客** - **&#x1f356; 原作者&#xff1a;[K同学啊](https://mtyjkh.blog.csdn.net/)** 我们接着上一篇文章配置完YOLOv5需要的环境后&#…

【Unity】云渲染

1 前言 最近在搞Unity云渲染的东西&#xff0c;所以研究了下官方提供的云渲染方案Unity Renderstreaming。注&#xff1a;本文使用的Unity渲染管线是URP。 2 文档 本文也只是介绍基本的使用方法&#xff0c;更详细内容参阅官方文档。官方文档&#xff1a;Unity Renderstreamin…

每日一道面试题---ArrayList的自动扩容机制(口述版本)

首先&#xff0c;ArrayList是基于动态数组实现的&#xff0c;它的容量是可以动态增长的&#xff0c;ArrayList的默认容量是10&#xff0c;当我们向ArrayList中插入一个数据时&#xff0c;第一步&#xff0c;会先进行一个条件的校验操作&#xff0c;先去判断ArrayList是不是一个…

分布式锁优化:使用Lua脚本保证释放锁的原子性问题

分布式锁优化&#xff08;二&#xff09;&#xff1a;使用Lua脚本保证释放锁的原子性问题 &#x1f4bb;黑马视频链接&#xff1a;Lua脚本解决多条命令原子性问题 在上一章节视频实现了一个可用的Redis分布式锁&#xff0c;采用SET NX EX命令实现互斥和过期自动释放机制&…

B1、进度汇报(— 25/05/31)

本文档汇总了各成员在 2025 年 5 月 11 日 ~ 5 月 31 日完成的工作。我们遇到了进度问题&#xff08;收工后需反思&#xff09;&#xff1a; 本学期第十四周&#xff08;05/19 ~ 05/25&#xff09;有相当多课程需要提交实验结果或上台展示。本学期第十六周&#xff08;06/02 ~…

BUUCTF[极客大挑战 2019]Havefun 1题解

BUUCTF[极客大挑战 2019]Havefun 1题解 题目分析解题理解代码逻辑&#xff1a;构造Payload&#xff1a; 总结 题目分析 生成靶机&#xff0c;进入网址&#xff1a; 首页几乎没有任何信息&#xff0c;公式化F12打开源码&#xff0c;发现一段被注释的源码&#xff1a; 下面我们…

常见算法题目5 -常见的排序算法

常见算法题目5 -常见的排序算法 本文介绍常见的排序算法的思路及代码实现(都是按照从小到大排列)&#xff0c;包括冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序。 1.冒泡排序 思路&#xff1a;重复遍历数组&#xff0c;依次比较相邻元素&#xff0c;若顺序错误…

3.需求分析与测试用例设计方法

设计方法 测试点 定义: 测试时需要考虑的可测试方面&#xff0c;不同公司可能称为"检查点"或其它名称特点: 是需求分析的最后一个环节&#xff0c;用于解决"测哪里"和"怎么测"的问题举例说明: 如同打架时的各种招数&#xff0c;如直接约架、设…

【PCB设计】STM32开发板——电源设计

电源稳压器&#xff08;Power Regulator&#xff09;是一种在电源电压或者负载电流发生变化的时候&#xff0c;依然能够提供稳定输出电压的元件。 一、关于LDO电路 1.引入 小灯泡实验 2.LDO原理 3.LDO芯片结构框图 PNP型三极管&#xff0c;Ube上升&#xff0c;截至&#xff…

BUUCTF[HCTF 2018]WarmUp 1题解

BUUCTF[HCTF 2018]WarmUp 1题解 分析解题过程代码审计主体函数CHECK函数&#xff1a; 构造payload 总结 分析 启动靶机&#xff0c;进入网址&#xff0c;是一张滑稽的表情包&#xff1a; 程序化F12查看源码&#xff1a; 发现注释内容&#xff0c;访问 url:/source.php得到…

如何使用DAXStudio将PowerBI与Excel连接

如何使用DAXStudio将PowerBI与Excel连接 之前分享过一篇自动化文章&#xff1a;PowerBI链接EXCEL实现自动化报表&#xff0c;使用一个EXCEL宏工作薄将PowerBI与EXCEL连接起来&#xff0c;今天分享另一个方法&#xff1a;使用DAX Studio将PowerBI与EXCEL连接。 下面是使用DAX S…

neo4j 5.19.0两种基于向量进行相似度查询的方式

介绍 主要讲的是两种相似度查询 一种是创建向量索引&#xff0c;然后直接从索引的所有数据中进行相似度搜索&#xff0c;这种不支持基于自己查询的结果中进行相似度匹配另一种是自己调用向量方法生产相似度进行相似度搜索&#xff0c;这种可以基于自己的查询结果中进行相似度…

中科院报道铁电液晶:从实验室突破到多场景应用展望

2020年的时候&#xff0c;相信很多关注科技前沿的朋友都注意到&#xff0c;中国科学院一篇报道聚焦一项有望改写显示产业格局的新技术 —— 铁电液晶&#xff08;FeLC&#xff09;。这项被业内称为 "下一代显示核心材料" 的研究&#xff0c;究竟取得了哪些实质性进展…

任务26:绘制1-12月各省份平均气温和预测可视化图形(折线

任务描述 知识点&#xff1a; DjangoECharts 重 点&#xff1a; DjangoECharts折线图 内 容&#xff1a; 绘制列表框&#xff0c;能够切换不同的省份根据ECharts官方示例&#xff0c;绘制ECharts折线图根据ECharts配置项手册&#xff0c;修改ECharts图形配置 任务指导…

【Redis】Set 集合

文章目录 常用命令saddsmemberssismemberscardspopsmovesrem 集合间操作sinter && sinterstoresunion && sunionstoresdiff && sdiffstore 内部编码应用场景 集合类型也是用于存储多个字符串类型的数据结构 集合中元素之间是 1. 无序的 2. 不允许重复的…