将图片存为二进制流到数据库并展示到前端的实现

article/2025/9/15 21:43:09

使用图片直接存储到数据库中可能会出现以下问题:

1.图片的存储太多了占用数据库的存储空间

2.图片占用内存较大在传输和渲染的情况下会影响应用性能

3.一般情况下是将图片上传云服务器然后数据库存地址,这里讲解的情况只适合图片较少的情景

这里使用的是微信小程序和webapi,sqlserver(理论上思路是一样的)

在微信小程序中我们先需要一个image容器存图片:

			<!-- 头像上传 --><view class="form-avatar-section"><view class="avatar-uploader {{avatar ? 'has-avatar' : ''}}" bindtap="chooseAvatar"><image class="avatar-preview" src="{{avatar || '/icons/photo-camera.png'}}" mode="aspectFill" /><view wx:if="{{!avatar}}" class="uploader-mask"><image src="/icons/add-photo.png" class="upload-icon" /><text>点击上传照片</text></view></view></view>

头像的样式你们也可以参考:

 

/* 头像上传区 */
.form-avatar-section {padding: 48rpx 0;background: #f8fafc;display: flex;justify-content: center;
}.avatar-uploader {width: 200rpx;height: 200rpx;border-radius: 50%;position: relative;border: 4rpx solid #e2e8f0;overflow: hidden;
}.avatar-preview {width: 100%;height: 100%;
}.uploader-mask {position: absolute;width: 100%;height: 100%;background: rgba(241, 245, 249, 0.8);display: flex;flex-direction: column;align-items: center;justify-content: center;
}.upload-icon {width: 56rpx;height: 56rpx;margin-bottom: 16rpx;opacity: 0.6;
}

以下是在js中的实现,因为我使用表单提交的,所以其中多了个formData, formData中的avatar是存储base64String类型数据,单独的avatar是存储的图片缓存地址

 

实现获取图片的方法:

 // 头像上传chooseAvatar() {var that = this;wx.chooseMedia({  //这个方法微信开发文档有详细讲解count: 1,mediaType: ['image'], //限制只能选中图片sizeType: ['compressed'],success: res => {const tempFile = res.tempFiles[0];// 检查文件大小(1MB = 1024*1024字节)限制2MB及以上图片不能上传if (tempFile.size > 2048 * 1024) {wx.showToast({title: '图片需小于2MB',icon: 'error',duration: 2000});return; // 终止执行}this.setData({avatar: res.tempFiles[0].tempFilePath   //将缓存地址赋值})var filePath = res.tempFiles[0].tempFilePath;this.convertToBase64(filePath).then(base => { //这里调用了文件转化方法console.log(base)that.setData({'formData.avatar': base   //这里是将base64的数据进行赋值})}).catch(err => {wx.showToast({title: err,icon: 'error'})});},fail: err => {},complete() {}})},

 以下是将文件转为base64类型的方法

  // 将图片转为base64文件流convertToBase64(tempFilePath) {return new Promise((resolve, reject) => {wx.getFileSystemManager().readFile({filePath: tempFilePath,encoding: 'base64',success: function (res) {resolve(res.data);},fail: function (error) {reject(error)}});})},

传输的数据如下:

 

 在后端只需要使用string类型将数据接收

按照我以下代码的顺序去实现:

首先我们先要有一个将对象带图片加入数据库的sql语句,这里使用的是参数化sql命令

因为图片较大会影响应用性能,所以在这里进行一个文件压缩,如果不需要压缩使用第二张图的方法:

 

如不需要压缩使用以下方法直接转为二进制流:

 如需要压缩,需要使用到的工具类如下:

  /// <summary>/// 图片压缩工具类/// </summary>public class ImageCompressor{public byte[] CompressImageFromBase64(string base64Data, long quality = 70L){// 1. 去除Base64头(如"data:image/png;base64,")//var cleanBase64 = base64Data.Split(',')[1];byte[] imageBytes = Convert.FromBase64String(base64Data);// 2. 加载图片并压缩using (var msInput = new MemoryStream(imageBytes))using (var image = Image.FromStream(msInput))using (var msOutput = new MemoryStream()){// 设置JPEG压缩质量(如果是PNG,调整格式)var encoderParams = new EncoderParameters(1);encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, quality);// 获取JPEG编码器var jpegEncoder = GetEncoder(ImageFormat.Jpeg);// 保存压缩后的图片image.Save(msOutput, jpegEncoder, encoderParams);return msOutput.ToArray();}}private ImageCodecInfo GetEncoder(ImageFormat format){var codecs = ImageCodecInfo.GetImageDecoders();foreach (var codec in codecs){if (codec.FormatID == format.Guid)return codec;}return null;}}

 当转换成功后,我们将转化的二进制流存入数据库

注意数据库中设计字段一定要为可变长的二进制数(这里使用varbinary(MAX)占用的数据库空间也比较大)

 二进制数存储方法如下,其他的数据就使用AddWithValue方式存储

如果你是循环增加的,需要在以下代码前面增加cmd.Parameters.Clear();防止其他问题报错

cmd.Parameters.Clear(); //清除参数

 将图片存入数据库后数据如下:

接下来我们需要取出数据进行展示,以下是我们通过sql将数据取出来后,取出的数据要转为byte[]的类型,然后在将byte[]类型转为base64String的数据返回给前端(同样是赋值给string类型)

 在我们获取到数据返回给前端后,我们需要将传过来的base64数据通过以下方法进行转化(转化的结果只能作为图片的存储地址,所以有以上结构进行赋值)

const dataURL = `data:image/png;base64,${dataItem.avatar}`;

赋值完成后,就可以显示出图片了

 


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

相关文章

pikachu通关教程-RCE

目录 RCE(remote command/code execute)概述: exec "ping" 管道符 乱码问题 RCE(remote command/code execute)概述: RCE漏洞&#xff0c;可以让攻击者直接向后台服务器远程注入操作系统命令或者代码&#xff0c;从而控制后台系统 分为远程代码和远程命令两种.当…

合合信息首批通过中国信通院文档图像篡改检测平台能力完备性测评

随着 AIGC 技术的迅速发展&#xff0c;图像篡改手段日益多样化和隐蔽化&#xff0c;给各行业带来了严峻挑战。虚假证照、伪造合同等文档不仅威胁企业的运营安全&#xff0c;也对社会诚信体系构成冲击。在中国信通院最新开展的文档图像篡改检测平台能力完备性测评中&#xff0c;…

线程池的详细知识(含有工厂模式)

前言 下午学习了线程池的知识。重点探究了ThreadPoolExecutor里面的各种参数的含义。我详细了解了这部分的知识。其中有一个参数涉及工厂模式&#xff0c;我将这一部分知识分享给大家~ 线程池的详细介绍(含工厂模式) 结语 分享到此结束啦。byebye~

力扣HOT100之动态规划:279. 完全平方数

这道题之前在刷代码随想录的时候做过&#xff0c;但是现在给忘干净了&#xff0c;现在甚至都不记得这是一个背包问题。。。又反过头去看代码随想录的视频才做出来的。这道题就是一个背包问题&#xff0c;这个问题可以抽象为&#xff1a;对于容量为j的背包&#xff0c;要计算出恰…

Pytorch Geometric官方例程pytorch_geometric/examples/link_pred.py环境安装教程及图数据集制作

最近需要训练图卷积神经网络&#xff08;Graph Convolution Neural Network, GCNN&#xff09;&#xff0c;在配置GCNN环境上总结了一些经验。 我觉得对于初学者而言&#xff0c;图神经网络的训练会有2个难点&#xff1a; ①环境配置 ②数据集制作 一、环境配置 我最初光想…

AI预测3D新模型百十个定位预测+胆码预测+去和尾2025年5月30日第93弹

从今天开始&#xff0c;咱们还是暂时基于旧的模型进行预测&#xff0c;好了&#xff0c;废话不多说&#xff0c;按照老办法&#xff0c;重点8-9码定位&#xff0c;配合三胆下1或下2&#xff0c;杀1-2个和尾&#xff0c;再杀4-5个和值&#xff0c;可以做到100-300注左右。 (1)定…

架构加速-深度学习教程

由于RK、jetson nano和电脑的GPU不相同&#xff0c;对应的pytorch也不同&#xff0c;因此不能直接将电脑训练好的模型丢到板端运行&#xff0c;因为训练的模型框架不同。就像你torch1.13和torch2.0都不一定支持&#xff0c;更何况不同平台上的torch。因此需要进行onnx模型转化&…

顶会新热门:机器学习可解释性

&#x1f9c0;机器学习模型的可解释性一直是研究的热点和挑战之一&#xff0c;同样也是近两年各大顶会的投稿热门。 &#x1f9c0;这是因为模型的决策过程不仅需要高准确性&#xff0c;还需要能被我们理解&#xff0c;不然我们很难将它迁移到其它的问题中&#xff0c;也很难进…

MicroPython+L298N+ESP32控制电机转速

要使用MicroPython控制L298N电机驱动板来控制电机的转速&#xff0c;你可以通过PWM&#xff08;脉冲宽度调制&#xff09;信号来调节电机速度。L298N是一个双H桥驱动器&#xff0c;可以同时控制两个电机的正反转和速度。 硬件准备&#xff1a; 1. L298N 电机控制板 2. ESP32…

Chainlink:连接 Web2 与 Web3 的去中心化桥梁

区块链技术通过智能合约实现了去中心化的自动执行&#xff0c;但智能合约无法直接访问链下数据&#xff0c;限制了其在现实世界的应用。Chainlink 作为去中心化预言机网络&#xff0c;以信任最小化的方式解决了这一问题&#xff0c;成为连接传统互联网&#xff08;Web2&#xf…

杨传辉:构建 Data × AI 能力,打造 AI 时代的一体化数据底座|OceanBase 开发者大会实录

5 月 17 日&#xff0c;OceanBase 在广州举办第三届开发者大会。主论坛环节&#xff0c;OceanBase CTO 杨传辉系统阐述了 Data AI 战略&#xff0c;并正式推出三大产品&#xff1a;PowerRAG、共享存储 及OceanBase桌面版。 杨传辉指出&#xff0c;数据与AI模型的一体化融合&a…

AU6825集成音频DSP的2x32W数字型ClaSSD音频功率放大器(替代TAS5825)

1.特性 ● 输出配置 - 立体声 2.0: 2 x 32W (8Ω,24V,THD N 10%) - 立体声 2.0: 2 x 26W (8Ω,21V,THD N 1%) ● 供电电压范围 - PVDD:4.5V -26.4V - DVDD: 1.8V 或者 3.3V ● 静态功耗 - 37mA at PVDD12V ● 音频性能指标 - THDN ≤ 0.02% at 1W,1kHz - SNR ≥ 107dB (A-wei…

关于ADS分辨率问题

笔记本上使用ADS&#xff08;Advanced Design System &#xff09;默认的界面挺大的&#xff0c;图标和字体都大&#xff0c;界面清新&#xff0c;给人一种呆呆易上手的感觉。 整个屏幕的截图 直到我打开了这个OPTIM的选项卡&#xff0c;它太长了&#xff0c;由于缩放太大&am…

海外DeepLink方案复杂?用openinstall一站式链接世界

App出海难免水土不服&#xff0c;商业模型、用户画像、增长方向没有一样是省心的&#xff0c;国内标配的DeepLink&#xff08;深度链接&#xff09;方案如果照搬出海同样无法达到最佳体验。 要知道国内外移动端生态是截然不同的&#xff0c;除了主流的URL Scheme和iOS Univers…

Ollama(1)知识点配置篇

ollama已经成功安装成功后&#xff0c;通常大家会对模型的下载位置和访问权限进行配置 1.模型下载位置修改 都是修改系统环境变量。 &#xff08;1&#xff09;默认下载位置 macOS: ~/.ollama/modelsLinux: /usr/share/ollama/.ollama/modelsWindows: C:\Users\你的电脑用户…

C# SolidWorks二次开发-实战1,找文件名不同实体相同的零件。

今天这篇文章话题来源于群里的聊天&#xff0c;在讨论有些插件功能的开发原理。 如标题&#xff0c;今天讲的是如何查找零件文件名不一样&#xff0c;但实际可能是同一个东西的办法。 - 题外话 熟悉Solidworks的人都知道&#xff0c;Solidworks有一个比较零件或者特征不同点的…

ES5时代的残党(被ES6淘汰的JS写法)

近年来&#xff0c;JavaScript语言经历了翻天覆地的变化。ES6(ECMAScript 2015)的发布标志着JavaScript进入了现代化时代&#xff0c;带来了大量新特性和更优雅的写法。但时至今日&#xff0c;许多开发者仍然固守着ES5时代的老旧模式&#xff0c;这不仅使代码显得过时&#xff…

【Python】4.字典和文件

文章目录 一、字典1、字典是什么&#xff1f;2、创建字典3、查找 key4、新增/修改元素5、删除元素6、遍历字典元素7、取出所有 key 和 value8、合法的 key 类型小结 二、文件1、文件是什么&#xff1f;2、文件路径3、文件操作1&#xff09;打开文件2&#xff09;关闭文件3&…

物流项目第十一期(智能调度之分配快递员)

本项目专栏&#xff1a; 物流项目_Auc23的博客-CSDN博客 整体核心业务流程 关键流程说明&#xff1a; 用户下单后&#xff0c;会产生取件任务&#xff0c;该任务也是由调度中心进行调度的订单转运单后&#xff0c;会发送消息到调度中心&#xff0c;在调度中心中对相同节点的运…

React 项目中封装 Excel 导入导出组件:技术分享与实践

文章目录 前言一、为什么需要封装 Excel 组件&#xff1f;二、技术选型三、核心实现1. 安装依赖2. 封装Excel导出3. 封装导入组件 &#xff08;UploadExcel&#xff09; 总结 前言 在 React 项目中&#xff0c;处理 Excel 文件的导入和导出是常见的业务需求。无论是导出报表数…