利用LRZ压缩与Base64编码实现高效文件上传

news2024/11/16 6:27:36

在这里插入图片描述

引言

在当今互联网时代,文件上传已成为众多在线服务不可或缺的一部分,尤其是在社交媒体平台上的照片分享和云存储服务中的文档管理等场景,高效且安全的文件上传机制对于保障用户体验至关重要。
为此,本文将介绍一种结合了LRZ压缩工具与Base64编码技术的优化文件上传方案。通过使用LRZ压缩工具对文件进行预处理,可以有效减小文件大小,进而提高上传效率并减少带宽消耗;而采用Base64编码则能够确保数据在网络传输过程中的完整性和安全性,从而为用户提供更加流畅和安全的文件上传体验。此方案特别适用于需要上传个人资料或头像等图片文件的应用场景。

使用LRZ上传

LRZ是一种高效的文件压缩工具,它支持多种压缩算法,能够在保持高压缩比的同时快速完成文件的压缩与解压操作。LRZ特别适用于大量小文件的压缩场景,因为它的性能优越,可以显著减少文件体积,加快网络传输速度。

Base64编码

在某些特定情况下,如通过电子邮件或HTTP请求发送二进制数据时,直接传输可能会遇到兼容性问题。此时,将文件转换为Base64格式可以有效解决这一问题。Base64编码将二进制数据转换为ASCII字符串,使得数据可以在任何传输介质上安全传输。

什么是Base64编码

定义

Base64是一种基于64个可打印字符来表示二进制数据的编码方式。它主要用于在网络上传输二进制数据,因为许多网络传输协议都是文本协议。这些字符包括A-Z、a-z、0-9以及两个额外的符号(通常是“+”和“/”)。每3个字节的二进制数据会被编码为4个Base64字符,因此Base64编码后的数据量会增加约33%。例如,100KB的二进制数据经过Base64编码后会变成约133KB。

工作原理

  1. 分组:将原始二进制数据按每3个字节一组进行分组。
  2. 转换:每个3字节的二进制数据被转换为4个6位的数值。
  3. 映射:每个6位的数值被映射到Base64编码表中的相应字符。
  4. 填充:如果最后一组不足3个字节,则使用“=”字符进行填充。

优缺点

  • 安全性:Base64编码不是加密方法,只是将二进制数据转换为文本数据,容易被解码。
  • 局限性:由于增加了数据量,不适合传输大量数据。
  • 优点:兼容性强,适用于多种传输协议;便于调试和日志记录。
  • 缺点:数据量增加,传输效率降低;编码和解码过程需要额外计算资源。

目的和应用场景

  • 目的:确保二进制数据在网络传输过程中不会被破坏。
  • 应用场景:电子邮件附件、网页中的图片嵌入、API请求中的二进制数据传输等。

上传功能的逻辑和代码

在这里插入图片描述
在这里插入图片描述

整体设计思路

  1. 用户选择图片文件。
  2. 使用lrz库对图片进行压缩。
  3. 将压缩后的图片转换为Base64格式。
  4. 通过AJAX将Base64字符串发送到服务器。
  5. 服务器接收到Base64字符串,解码并保存图片。
  6. 返回图片的URL给前端。

示例代码

前端代码

<asp:Content ID="Content3" ContentPlaceHolderID="ScripttPlaceHolder2" runat="server">
    <!-- 引入LRZ压缩库 -->
    <script src="lib/lrz/dist/lrz.bundle.js" type="text/javascript"></script>
    <!-- 引入jQuery库 -->
    <script src="Scripts/jquery-3.7.0.min.js" type="text/javascript"></script>
    <script>
        // 当文件输入框发生变化时触发事件
        $$("#upload").on("change", function () {
            // 使用LRZ库对选中的文件进行压缩,设置压缩后的宽度和高度为300像素
            lrz(this.files[0], { width: 300, height: 300 }).then(function (rst) {
                // 异步上传压缩后的图片
                $.post("ashx/UploadAvatar.ashx", { len: rst.base64Len, baseString: encodeURI(rst.base64) },
                    function (res) {
                        // 如果上传成功
                        if (res.State == 1) {
                            // 将上传成功的图片路径存储到隐藏控件中,用于后续更新使用
                            $("#hfAvatar").val(res.Message);
                            // 创建一个新的Image对象
                            var image = new Image();
                            // 设置图片的源路径
                            image.src = res.Message;
                            // 设置图片的宽度和高度
                            image.width = 100;
                            image.height = 100;
                            // 将图片添加到父元素中
                            $("#uploadselect").parent().append(image);
                            // 移除原来的上传按钮
                            $("#uploadselect").remove();
                        } else {
                            // 如果上传失败,弹出提示
                            alert("上传失败");
                        }
                    }, "json");
            });
        });
    </script>
</asp:Content>
前端代码
  1. 引入LRZ压缩库和jQuery库

    • lrz.bundle.js:用于图片压缩。
    • jquery-3.7.0.min.js:用于DOM操作和AJAX请求。
  2. 文件输入框变化事件

    • 使用$$("#upload").on("change", function () { ... })监听文件输入框的变化。
    • 使用lrz(this.files[0], { width: 300, height: 300 })对选中的文件进行压缩,设置压缩后的宽度和高度为300像素。
  3. 异步上传

    • 使用$.post方法发送AJAX请求,将压缩后的Base64字符串和长度发送到服务器。
    • 如果上传成功,将返回的图片路径存储到隐藏控件中,并创建一个新的Image对象显示图片。
    • 如果上传失败,弹出提示。

后端代码

using HPIT.Model;
using Newtonsoft.Json;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Web;

namespace HPITAixiu.ashx
{
    /// <summary>
    /// 处理头像上传的一般处理程序
    /// </summary>
    public class UploadAvatar : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            // 从请求中获取Base64字符串的长度
            int len = int.Parse(context.Request.Form["len"]);
            // 如果长度小于等于0,返回400错误状态码
            if (len <= 0)
            {
                context.Response.StatusCode = 400;
                context.Response.End();
                return;
            }
            // 从请求中获取Base64字符串的长度
            int base64Length = context.Request.Form["baseString"].Length;
            // 如果Base64字符串长度小于等于0,返回400错误状态码
            if (base64Length <= 0)
            {
                context.Response.StatusCode = 400;
                context.Response.End();
                return;
            }

            // 将前台传过来的Base64格式的文件进行解码,存储到字节数组中
            // 注意:这里使用了HttpUtility.UrlDecode来解码URL编码的Base64字符串
            byte[] bytes = new byte[HttpUtility.UrlDecode(context.Request.Form["baseString"]).Length];
            // 如果压缩没有问题,传输到服务器上的文件长度和压缩的文件长度应相等
            if (len == bytes.Length)
            {
                // 获取Base64字符串中实际的图像数据部分,去掉前缀(如"data:image/jpeg;base64,")
                var baseString = context.Request.Form["baseString"].Split(',')[1];
                // 将Base64编码的字符串转换成字节数据
                byte[] newType = Convert.FromBase64String(baseString);
                // 生成一个随机文件名,避免上传的名字相同被覆盖
                string randomString = Guid.NewGuid().ToString();
                // 设置上传路径
                string filePath = $"{context.Server.MapPath("~/avatar/")}{randomString}.jpg";
                // 定义一个用于返回图片上传成功的路径
                string imageUrl = $"/avatar/{randomString}.jpg";
                // 将文件在内存流中进行传输
                using (MemoryStream memoryStream = new MemoryStream(newType))
                {
                    // 从内存流中将图片读取出来
                    using (Image image = Image.FromStream(memoryStream))
                    {
                        // 将读取出来的图片存储到指定的路径下
                        image.Save(filePath, ImageFormat.Jpeg);
                    }
                }

                // 创建一个AjaxResult对象,用于返回上传结果
                AjaxResult ajaxResult = new AjaxResult
                {
                    State = 1, // 表示上传成功
                    Message = imageUrl // 上传成功的图片路径
                };
                // 将当前返回的Ajax结果进行JSON序列化并响应到前台
                context.Response.Write(JsonConvert.SerializeObject(ajaxResult));
            }
            else
            {
                // 如果文件长度不匹配,返回400错误状态码
                context.Response.StatusCode = 400;
                context.Response.End();
            }
        }
    }
}
后端代码
  1. 设置响应内容类型

    • context.Response.ContentType = "text/plain":设置响应的内容类型为纯文本。
  2. 获取Base64字符串的长度

    • int len = int.Parse(context.Request.Form["len"]):从请求中获取Base64字符串的长度。
    • 如果长度小于等于0,返回400错误状态码。
  3. 获取Base64字符串

    • string baseString = context.Request.Form["baseString"]:从请求中获取Base64字符串。
    • 如果Base64字符串为空,返回400错误状态码。
  4. 解码Base64字符串

    • byte[] bytes = Convert.FromBase64String(baseString.Split(',')[1]):解码Base64字符串,去掉前缀(如"data:image/jpeg;base64,")。
  5. 生成随机文件名

    • string randomString = Guid.NewGuid().ToString():生成一个随机文件名,避免文件名冲突。
    • string filePath = context.Server.MapPath($"~/avatar/{randomString}.jpg"):设置上传路径。
  6. 保存图片

    • 使用MemoryStream将文件在内存流中进行传输。
    • 使用Image.FromStream(memoryStream)从内存流中读取图片。
    • 使用image.Save(filePath, ImageFormat.Jpeg)将图片保存到指定路径。
  7. 返回上传结果

    • 创建一个AjaxResult对象,用于返回上传结果。
    • 使用JsonConvert.SerializeObject(ajaxResult)将结果进行JSON序列化并响应到前台。
  8. 是否可重用

    • public bool IsReusable { get { return false; } }:表示该处理程序是否可以重用。

总结

通过本文,我们详细介绍了如何使用LRZ压缩工具上传图片,并结合Base64编码进行处理。这种方式不仅提高了文件传输的效率,还确保了数据的完整性和兼容性。希望本文能对您有所帮助,鼓励您尝试并在实际项目中应用这些技术。

参考资料

  • LRZ官方文档
  • Base64编码详解
  • jQuery官方文档
  • C#官方文档

希望这篇博客文章能够帮助您更好地理解和应用LRZ压缩和Base64编码技术。如果有任何问题或需要进一步的帮助,请随时联系我。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

汇川AM400脉冲轴控制(轴控功能块ST源代码)

汇川AM400如何和编程软件通信连接 汇川AM400PLC如何和编程软件通信连接_汇川am400读取程序-CSDN博客文章浏览阅读159次。本文介绍了如何使用CODESYS编程软件与汇川AM400PLC进行通信连接,包括扫描网络、修改IP地址、刷新日志和下载监控程序的步骤。同时,文章提到了CODESYS编程…

灯塔:JavaScript

Web标准也称为网页标准&#xff0c;由一系列的标准组成&#xff0c;大部分由W3C&#xff08;World Wide Web Consortium,万维网联盟&#xff09;负责制定。 三个组成部分&#xff1a; HTML&#xff1a;负责网页的基本结构&#xff08;页面元素和内容&#xff09;。 CSS&…

go 安装依赖超时

一、配置代理 go env -w GO111MODULEon go env -w GOPROXYhttps://goproxy.io,direct go get github.com/unidoc/unioffice

ODrive电机驱动算法VScode环境配置笔记教程

1、ODrive基本介绍 ODrive 是一个开源的优秀电机控制器项目&#xff0c;旨在为各种应用提供高性能、高可靠性的电机控制解决方案。这个项目是专门用于驱动无刷直流电机&#xff08;BLDC&#xff09;和永磁同步电机&#xff08;PMSM&#xff09;的高性能开源伺服控制系统。ODriv…

AI绘制调整虚线教程

1、打开ai的软件&#xff0c;执行菜单栏中的文件—新建&#xff0c;新建一个大小任意的画板&#xff0c;画板大小根据自己的需要来设置。 2、选择工具箱中的直线段工具&#xff0c;将填充设置为无&#xff0c;描边设置为黑色&#xff0c;描边大小稍微设置大一点&#xff0c;画一…

【学习笔记】STM32F407探索者HAL库开发(五)F407时钟系统配置

【学习笔记】STM32F407探索者HAL库开发&#xff08;四&#xff09;F407时钟系统配置 1 F407_CubeMX时钟树配置&#xff08;传送门&#xff09;2 STM32F407时钟树2.1 STM32F407时钟系统图2.2 STM32F103时钟树简图2.2.1 高速部分2.2.2 低速部分 2.3 时钟源2.3.1 外部时钟源2.3.2 …

SOCKS5、HTTP 代理IP协议有何区别?

在网络通信领域&#xff0c;代理服务器的选择对于数据安全和传输效率至关重要。SOCKS5代理和HTTP代理作为两种常用的代理类型&#xff0c;各自具有独特的特点和适用场景。本文将深入探讨SOCKS5代理与HTTP代理的区别、特性及应用场景&#xff0c;为用户提供选择指南。 一、SOCK…

数据结构:二叉树(一)

ps&#xff1a;偷懒了几天&#xff0c;接着更新 树的概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。 把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的…

MODIS/Landsat/Sentinel下载教程详解【常用网站及方法枚举】

⛄前言 在当今快速发展的地球观测时代&#xff0c;遥感技术作为获取地球表面及其环境信息的重要手段&#xff0c;正以前所未有的广度和深度改变着我们对自然界的认知与管理方式。MODIS&#xff08;Moderate-resolution Imaging Spectroradiometer&#xff0c;中分辨率成像光谱…

【全网最全】2024华为杯研赛D题完整代码建模过程+py代码(后续会更新)

您的点赞收藏是我继续更新的最大动力&#xff01; 一定要点击如下的卡片&#xff0c;那是获取资料的入口&#xff01; 点击链接加入【2024华为杯研赛资料汇总】&#xff1a;https://qm.qq.com/q/XzdIsvbiM0 https://qm.qq.com/q/XzdIsvbiM0 问题一 .在众多描述地理环境的变…

科研绘图系列:R语言箱线图和连线图(boxplot linechart)

文章目录 介绍加载R包导入数据画图1画图2画图3画图4系统信息介绍 箱线图表示组间差异,连线图表示数据波动。 加载R包 library("here") library("tidyverse") library("ggpubr") library("scales"

Git从了解到操作

Git常用命令 基本的linux命令 ls / ll 查看当前目录( ls 是查看目录有哪些文件夹&#xff0c;ll 是查看隐藏文件)cat 查看文件内容touch 创建文件vi vi编辑器 (使用 vi 编辑器是为了方便展示效果&#xff0c;也可以记事本、editPlus、notPad等其它编辑器) 备注 Git GUl: Gi…

数值计算 --- 平方根倒数快速算法(0x5f3759df,这是什么鬼!!!)

平方根倒数快速算法 --- 向Greg Walsh致敬&#xff01; 写在最前面&#xff1a; 上图中的这段代码出自一个早期的3D游戏<雷神之锤>的源代码&#xff0c;它实现的功能就是计算一个数x的平方根的倒数&#xff1a; 这段代码之所以称之为经典&#xff0c;私以为主要是因为以下…

51单片机——LED灯篇

一、LED与单片机P2管脚相连 二、点亮一个LED灯 #include <STC89C5xRC.H> void main() { P2 0xFE; //1111 1110 } P2有8个管脚&#xff0c;对应8个二进制位。 LED灯右侧接电源是正极&#xff08;1&#xff09;&#xff0c;左侧给负极&#xff08;0&#xff09;即可…

SpringBoot教程(三十) | SpringBoot集成Shiro权限框架(shiro-spring 方式)

SpringBoot教程&#xff08;三十&#xff09; | SpringBoot集成Shiro权限框架&#xff08;shiro-spring方式&#xff09; 一、 什么是Shiro二、Shiro 组件核心组件其他组件 三、流程说明shiro的运行流程 四、SpringBoot 集成 Shiro1. 添加 Shiro 相关 maven2. 添加 其他 maven3…

链表(3)链表的基本操作

单链表的基本操作主要有;①创建链表;②输出链表;③査我结点;④插入结点,⑤鹏除结点;⑥重组链表。下面分别进行介绍。 一.创建链表 创建链表是指在程序运行时,进行动态内存分配,创建若千个结点,并把这些结点连接成串,形成一个链表。在进行动态内存分配时,需要使用在&#xff08…

QT快速安装使用指南

在Ubuntu 16.04上安装Qt可以通过多种方式进行。以下是使用Qt在线安装程序和apt包管理器的两种常见方法&#xff1a; 方法一&#xff1a;使用Qt在线安装程序 下载Qt在线安装程序 访问Qt官方网站&#xff1a;Try Qt | Develop Applications and Embedded Systems | Qt找到并下载…

Swift里的数值变量的最大值和最小值

Swift里有很多种数值变量&#xff0c;如Int&#xff0c;Int8&#xff0c;Float&#xff0c;Double等。和绝大多数编程语言一样&#xff0c;由于是在计算机上运行&#xff0c;内存有限&#xff0c;所以必有最大值和最小值&#xff0c;而计算机无法处理超过该值的数。 在Swift中…

【Linux】POSIX信号量、基于环形队列实现的生产者消费者模型

目录 一、POSIX信号量概述 信号量的基本概念 信号量在临界区的作用 与互斥锁的比较 信号量的原理 信号量的优势 二、信号量的操作 1、初始化信号量&#xff1a;sem_init 2、信号量申请&#xff08;P操作&#xff09;&#xff1a;sem_wait 3、信号量的释放&#xff08…

网络安全-webshell绕过,hash碰撞,webshell绕过原理

目录 一、题目 1.1 1.2 1.3 1.4 1.5 二、绕过动态检测引擎的一次尝试 三、一个比赛中的webshell 四、webshell绕过的原理以及哈希碰撞 五、JSP解释流程导致的绕过&#xff08;QT比赛&#xff09; 5.1环境 5.2例子 一、题目 这里我们通过几道题目来给大家讲解 1.…