当前课程知识点:数据库技术与程序设计 > 综合练习题库 > 综合练习题库 > 技术分享贴:如何在数据库中保存大量图片
我们将图片保存到数据库中,使用维护起来都变得很简单尤其适用于小型便携式的Access管理系统。但如果直接通过绑定对象框控件的插入对象方法将图片插入的话,非位图图片体积会暴增几十上百倍,从而大大降低了实用性。
一般情况下,如果要将图片保存到数据库中,都是通过绑定对象框的“插入对象”功能来实现,但是这样做会造成数据库体积的明显增大。尤其是在Access 2007之前的版本中所有插入的图上均会被转换成位图,而如果把一个JPG图片转换成位图,我们会发现图片的大小增大了几十上百倍。那么有没有一种办法能够直接把保存源格式的图片到数据库中呢?答案是肯定的,就是ADO中的流对象(Stream)。此处要注意的是,ADO必须是2.5以及更新的版本,老版本中是没有流对象的。
流对象主要有两种用途:一种是处理文档数据,这样可以通过流对象的属性和方法来读取和修改文档内容;另一种就是把其它任意格式的文件以二进制数据流进行处理,不关心文件的格式和内容。在本文中我们讨论的是在数据库中存储图片,所以我们这里主要讨论的就是它的后一种用途。为了更容易理解,我们在此基于一个示例程序来进行说明。
一、创建表
首先我们需要在表中添加至少两个字段,一个用来存放图片的名称,一个用来存放图片的二进制文件数据:
二、创建窗体
然后我们基于此表来创建窗体,通过窗体实现图片的保存以及将保存的图片显示出来。在此窗体中我们需要手动添加三个控件:
图像控件:名称:imgPic 图片类型:链接
按钮控件:名称:cmdAdd 标题:添加/更改图片
按钮控件:名称:cmdDel 标题:删除图片
由于相关的记录修改添加都是通过代码完成,所以我们需要将“图片名称”的“锁定”属性设为“是”,另外图片数据是一个绑定对象框控件,它只用来存放图片文件数据,不需要显示出来,所以我们要将其“可见性”属性设为“否”。
三、添加代码
接下来我们需要在单击“添加/更改图片”按钮时将图片以二进制方式写入到数据库中,及以在窗体的记录切换时自动将二进制数据再还原为图片文件,并以链接的方式显示在图像控件中,这些都需要以编程方式来实现,具体实现代码如下:
'添加图片并将图片保存到数据库中
Private Sub cmEdit_Click() Dim stm As ADODB.Stream '定义流对象变量 Dim strPathName As String '文件名临时变量 '调用Access通用的文件选取对话框来选择一个图片文件(需要最低2003版Access) With FileDialog(3) 'msoFileDialogFilePicker '清除原有文件类型筛选 .Filters.Clear '添加自定义文件类型筛选 .Filters.Add "图片文件", "*.jpg;*.gif;*.png" '如果对话框未被取消,则将选取的文件名保存到变量 If .Show Then strPathName = .SelectedItems(1) End With '如果变量不为空说明对话框没有被取消 If strPathName <> "" Then '初始化流对象 Set stm = New ADODB.Stream '设置为二进制处理方式 stm.Type = adTypeBinary '设置为读写权限模式 stm.Mode = adModeReadWrite '打开流对象 stm.Open '从将文件加载到流对象 stm.LoadFromFile strPathName '将流对象中的二进制数据保存到数据库中 Me!图片数据 = stm.Read '关闭流对象 stm.Close '在图像控件中显示刚才的图片 Me.imgPic.Picture = strPathName '将图片的文件名保存到“图片名称”字段,不保存路径 Me!图片名称 = Mid$(strPathName, InStrRev(strPathName, "\") + 1) End If '销毁对象变量 Set stm = Nothing End Sub '从数据库中删除图片 Private Sub cmdDel_Click() Me!图片数据 = Null '清空图片数据字段 Me!图片名称 = Null '清空图片名称字段 Me.imgPic.Picture = "" '清除图像控件中显示的图片 End Sub
'通过成为当前事件,实现记录切换时自动显示图片
Private Sub Form_Current() Dim stm As ADODB.Stream '定义流对象变量 Dim strPathName As String '文件名临时变量 '如果“图片数据”字段不为空 If Not IsNull(Me!图片数据) Then '根据“图片名称”字段生成一个到操作系统临时文件夹的路径名 strPathName = Environ$("Temp") & "\" & Me!图片名称 '初始化流对象变量 Set stm = New ADODB.Stream '设置为二进制处理方式 stm.Type = adTypeBinary '设置为读写权限模式 stm.Mode = adModeReadWrite '打开流对象 stm.Open '将数据库中的二进制数据写入流对象变量 stm.Write Me!图片数据 '另存为文件,如果文件存在则覆盖 stm.SaveToFile strPathName, adSaveCreateOverWrite '关闭流对象 stm.Close '在图像控件中显示刚才保存的图片 Me.imgPic.Picture = strPathName Else '如果当前记录中没有图片数据,则清除图像控件中的显示 Me.imgPic.Picture = "" End If '销毁对象变量 Set stm = Nothing End Sub
四、运行测试
最后,就是测试了,大家快去试一下吧。
资料来源:公众号Access开发
-知识点拼图+问题求解流程+软件工程开发教学流程——写给翻转课堂开课教师
-技术分享贴续篇:怎样用窗体显示一条记录存储的多张OLE图像文件?
-技术分享贴:复杂的SQL自体连接和嵌套查询,涨粉最多的用户ID和涨粉数
-往届竞赛获奖作品展示
-1.1 数据与数据管理
--【拓展阅读】到底什么是IT(Information Technology)
-1.2 DBS=DB+DBMS
-1.3 不以六律不能正五音——数据模型
-- 课件1.3.1 数据模型
-1.4 数据库系统结构
-本章小结
--第一章小结
-第一章作业
-2.1 数据库设计流程
-2.2 概念结构设计
-2.3 逻辑结构设计
-本章小结
--第二章小结
-第二章作业
-3.1 数据库管理系统
-3.2 创建数据库
-3.3 创建数据表
-3.4 维护数据表
-本章小结
--第三章小结
-第三章作业
-4.1 基本数据类型
-4.2 常量
--4.2.1 常量
-4.3 变量和数组
--4.3.1 变量
-4.4 表达式和函数
-本章小结
--第四章小结
-第四章作业
-【讨论帖:悬赏!谁能解决Round()函数Banker’s rounding算法的bug?】
-5.1 数据检索方法
-5.2 数据库查询文件
-5.3 选择查询
-5.4 参数查询
-5.5 操作查询
-本章小结
--第五章小结
-第5章作业
-6.1 SQL概述
-6.2 SQL数据定义语言
-6.3 SQL数据查询语言
-6.4 SQL数据操作语言
-本章小结
--第六章小结
-第6章作业
-【讨论帖:你是否听说过“自然语言检索”,你在什么地方见到过,或者使用过“自然语言检索”吗?】
-7.1 窗体设计
-7.2 报表设计
-本章小结
--第七章小结
-第七章作业
-【讨论帖:你能总结一下窗体和报表的共性和区别吗?在你的工作、学习或生活中,你都见到过哪些窗体和报表的实际应用?】
-8.1 VBA编程基础
-8.2 顺序结构及常用命令
-8.3 分支结构
--8.3.2 多路分支选择语句Select Case 和分支嵌套
--课件8.3.2 多路分支选择语句Select Case 和分支嵌套
-8.4 循环结构
-8.5 函数与过程
-8.6 VBA程序调试
-8.7 数组
-本章小结
--第八章小结
-第八章作业
-【讨论帖:我们学习了VBA面向过程的程序设计,你能结合实践,谈谈自己对算法和程序的理解吗?】
-9.1 面向对象的基本概念
-9.2 控件对象的属性和方法
-9.3 控件对象的事件
-9.4 窗体的面向对象程序设计
-【拓展阅读】【综合案例】Word中的查找与替换是如何实现的?
-本章小结
--第九章小结
-第九章作业
-【讨论贴:本章用小黄鸭类比了面向对象的各种概念,你能也用类比的方式谈谈你对面向对象的理解吗?】
-10.1 宏的基本概念
-10.2 宏的创建与调用
-10.3 数据宏
-10.4 宏的调试和转换
-【拓展阅读】【综合案例】一句代码不敲,就开发了一个航班查询系统?
-本章小结
--第十章小结
-第十章作业
-【讨论帖:王者、LOL、魔兽、DOTA……,说说你在虚拟世界里用宏(超级宏)所向披靡的故事吧!】
-11.1 数据库应用系统结构
-11.2 教学教务管理系统功能需求
-11.3 教学教务管理系统底层数据结构
-11.4 登录模块实现
-11.5 学生管理模块实现
-11.6 教学管理模块实现
-11.7 系统测试与发布
-本章小结
--第十一章小结
-课程综合设计
-综合练习题库