解决方法一般有两种:
2、将图片以二进制数据流的形式直接写入数据库字段中。
以下为具体方法:
一、保存图片的上传路径到数据库:
string
uppath=""//用于保存图片上传路径
//获取上传图片的文件名
string fileFullname =
this.FileUpload1.FileName
//获取图片上传的时间,以时间作为图片的名字可以防止图片重名
string
dataName =
DateTime.Now.ToString("yyyyMMddhhmmss")
//获取图片的文件名(不含扩展名)
string
fileName = fileFullname.Substring(fileFullname.LastIndexOf("\\") +
1)
//获取图片扩展名
string type =
fileFullname.Substring(fileFullname.LastIndexOf(".") +
1)
//判断是否为要求的格式
if (type == "bmp" || type == "jpg" || type == "jpeg"
|| type == "gif" || type == "JPG" || type == "JPEG" || type == "BMP" || type ==
"GIF")
{
//将图片上传到指定路径的文件夹
this.FileUpload1.SaveAs(Server.MapPath("~/upload")
+ "\\" + dataName + "." +
type)
//将路径保存到变量,将该变量的值保存到数据库相应字段即可
uppath
= "~/upload/" + dataName + "." +
type
}
二、将图片以二进制数据流直接保存到数据库:
引用如下命名空间:
using
System.Drawing
using System.IO
using
System.Data.SqlClient
设计数据库时,表中相应的字段类型为iamge
保存:
//图片路径
string
strPath = this.FileUpload1.PostedFile.FileName.ToString
()
//读取图片
FileStream fs = new System.IO.FileStream(strPath,
FileMode.Open, FileAccess.Read)
BinaryReader br = new
BinaryReader(fs)
byte[] photo =
br.ReadBytes((int)fs.Length)
br.Close()
fs.Close()
//存入
SqlConnection
myConn = new SqlConnection("Data Source=.Initial Catalog=stumanageUser
ID=saPassword=123")
string strComm = " INSERT INTO
stuInfo(stuid,stuimage) VALUES(107,@photoBinary
)"// *** 作数据库语句根据需要修改
SqlCommand myComm = new SqlCommand(strComm,
myConn)
myComm.Parameters.Add("@photoBinary", SqlDbType.Binary,
photo.Length)
myComm.Parameters["@photoBinary"].Value =
photo
myConn.Open()
if (myComm.ExecuteNonQuery() >
0)
{
this.Label1.Text =
"ok"
}
myConn.Close()
读取:
...连接数据库字符串省略
mycon.Open()
SqlCommand
command = new
SqlCommand("select stuimage from stuInfo where stuid=107",
mycon)//查询语句根据需要修改
byte[] image = (byte[])command.ExecuteScalar
()
//指定从数据库读取出来的图片的保存路径及名字
string strPath =
"~/Upload/zhangsan.JPG"
string strPhotoPath =
Server.MapPath(strPath)
//按上面的路径与名字保存图片文件
BinaryWriter bw = new
BinaryWriter(File.Open(strPhotoPath,FileMode.OpenOrCreate))
bw.Write(image)
bw.Close()
//显示图片
this.Image1.ImageUrl
= strPath
采用这两种方式可以根据实际需求灵活选择。
图片数据库的设计:A表为明细信息,B表是图册,属于汇总信息多对一的关系所以A表增加字段,记录图册编号就可以了
如果有已存在的图片想另编成册,就需要在A表复制已存在数据写入新图册在B表的编号吧?或者有其它更优算法吗?
如果你想保留这张图片历史上存在于哪些图册,有两种方法,一是新建一条记录,原图册也能正常打开;二是建立一个历史关系表,只保留变更过的图片与图册对应关系,这样要想显示原图册程序上费点劲,好处是图片库都是唯一的,不乱。
如果不保留痕迹,将图册字段变更就行。
因为你这个不存在什么逻辑关系,就没有什么所谓算法问题,搞个前台界面,勾选信息,然后通过循环,进行数据处理。速度不见得慢。
望采纳!!!感激感激
图像数据在数据库内部的存储原理:XML 是文本型的数据交换结构,对于字符类型的文本交换非常的方便,实际工作中我们往往需要通过 XML 将二进制格式的图形图像信息数据进行数据交换。本文从介绍 BASE64 编码的原理入手,通过采用 C 语言编写 DB2 的嵌入存储过程,实现了在数据库内存中将文本格式的图片文件到二进制 BLOB 字段之间的转换,并且就性能优化等提出若干建议,该设计思路和程序可以广泛的应用到图像图形数据在 XML 的存储和转换。
--------------------------------------------------------------------------------
回页首
XML 存储图形图像的基本原理
XML 作为一种非常广泛的数据交换的载体被广泛的应用到了各行各业的数据交换中。对于图形图像数据的转换,需要采用 Base64 编码将二进制格式的图形图像信息转换成文本格式再进行传输。
Base64 编码转换的思想是通过 64 个 ASCII 字符码对二进制数据进行重新编码组合,即将需要转换的数据每三个字节(24 位)为一组,再将这 24 位数据按每组 6 位进行重新划分,在每组的最高 2 位填充 0 最终成一个完整的 8 位字节。如果所要编码的数据的字节数不是 3 的整数倍,需要在最后一组数据填充 1 到 2 个字节的 0 字节。例如:我们对 ABC 进行 BASE64 的编码,ABC 的编码值:A(65), B(66), C(67)。再取二进制 A(01000001)B(01000010)C(01000011)连接起来构成 010000010100001001000011,然后按 6 位为单位分成 4 个数据块并在最高位填充两个 0 后形成 4 个字节的编码后的值(00010000)(00010100)(00001001)(00000011)。再将 4 个字节的数据转换成十进制数为(16)(20)(19)(3)。最后根据 BASE64 给出的 64 个基本字符表,查出对应的 ASCII 码字符(Q)(U)(J)(D)。这里的值实际就是数据在字符表中的索引。
BASE64 字符表:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789。
某项目的数据交换采用 XML 的为介质,XML 的结构包括个人基本信息:姓名、性别、相片等信息,其中相片信息是采用经过 BASE64 函数转换后的文本型数据,图像图形信息通过 BASE64 进行数据转换后,形成文本格式的数据类型,再将相应的数据存放到 XML 中,最终形成可供交换的文本型的 XML 数据结构。
XML 的数据结构如下所示:
<?xml version=”1.0” encoding=”UTF-8” ?>
<HeadInfo>
<TotalNum>10<TotalNum>
<TransDate>2007-10-18</TransDate>
</HeadInfo>
<Data>
<Name>张三 </Name>
<Sex>男 </Sex>
<Photo>/9j/4AAQSkZJRgABAQAAAQABAAD......</Photo>
<Data>
--------------------------------------------------------------------------------
回页首
相片数据在 DB2 嵌入式 C 程序的实现方法
该项目要求能够在 DB2 数据库中将相片数据存储为二进制 BLOB 格式。我们采用 DATASTAGE 进行 XML 数据加载,将 XML 中的姓名、性别等基本数据项加载到相应的字段,其中文本型的相片数据则加载到 CLOB 字段中,再按照 BASE64 的编码规则进行逆向转码,整个数据流程如下图所示:
图 1. 相片存储流程图
用户的相片每天的更新数据为 30 万条,而且每个相片的平均大于 32KB,为了获得最佳的数据库性能,选择采用 C 存储过程的方式开发了 BASE64 的转换函数。每次函数读取存储在 CLOB 字段的文本格式数据全部存储到内存中,并且通过 decode 函数在内存中进行转码,转码后再存入数据库中。
程序的清单 1 是逐行读取 CLOB 字段,并且调用 decode 函数进行转码;程序的清单 2 是 decode 函数的关键性代码。完整的程序见源代码下载部分。
清单 1. 读入 CLOB,写入 BLOB 字段
EXEC SQL BEGIN DECLARE SECTION
SQL TYPE IS CLOB(100 K) clobResume//CLOB 结构体变量
SQL TYPE IS BLOB(100 K) blobResume//BLOB 结构体变量
sqlint16 bobind
sqlint16 lobind
sqlint16 cobind
sqlint32 idValue
EXEC SQL END DECLARE SECTION
int clob2bin(void)
{
// 声明 SQLCA 结构
struct sqlca sqlca
int charNb
int lineNb
long n
n=0
// 定义数据库游标
EXEC SQL DECLARE c1 CURSOR WITH HOLD FOR
SELECT czrkxp_a
FROM CZRK_blob for update
EXEC SQL OPEN c1
// 活动 CLOB 字段的信息,已经 CLOB 字段的大小
EXEC SQL FETCH c1 INTO :clobResume:cobind
// 循环读取 CLOB 字段,并且调用 DECODE 转码函数
while (sqlca.sqlcode != 100)
{
if (cobind <0)
{
printf(“ NULL LOB indicated.\n”)
}
else
{
n++
decode()// 文本格式到二进制流的转码函数
printf(“\nCurrent Row =%ld”,n)
// 数据写入 BLOB 字段
EXEC SQL update czrk_blob set czrkxp_blob = :blobResume
where current of c1
// 提交事务
EXEC SQL COMMIT
}
EXEC SQL FETCH c1 INTO :clobResume:cobind
}
// 关闭游标
EXEC SQL CLOSE c1
EXEC SQL COMMIT
return 0
}
清单 2. 文本文件到二进制文件的转换
void decode( void )
{
unsigned char in[4], out[3], v
int I, len
long j,k
j = -1
k=0
// 将读入 CLOB 结构体变量的数据进行转换
while( j <clobResume.length){
for( len = 0, I = 0I <4 &&( j <clobResume.length )i++ ) {
v = 0
while((j <clobResume.length) &&v == 0 ) {
j++
v = (unsigned char) clobResume.data[j]
v = (unsigned char) ((v <43 || v >122) ? 0 : cd64[ v – 43 ])
if( v ) {
v = (unsigned char) ((v == ‘$’) ? 0 : v – 61)
}
}
if( j <clobResume.length ) {
len++
if( v ) {
in[ I ] = (unsigned char) (v – 1)
}
}
else {
in[i] = 0
}
}
if( len ) {
decodeblock( in, out )
// 写入到 BLOB 结构体变量中
for( I = 0I <len – 1i++ ) {
blobResume.data[k] = out[i]
k++
}
}
}
blobResume.length= k
}
--------------------------------------------------------------------------------
回页首
数据的转换效率和优化建议
在 IBM P570 数据库服务器上运行,该程序的运行效率非常高,先后进行了几个数量级的测试,最终平均测试的转换效率为:每 1 万笔数据记录,转换的效率 55 秒,即 182 条 / 秒。值得注意的是,整个转换过程占用 CPU 的量并不特别大,主要的性能瓶颈在磁盘阵列中。
以后可以进一步在以下方面进行调优,确保程序转换的效率更高:
1)采用多进程调用的方式,以获得更高的并发数量;
2)采用每 10 次或者 100 次提交事务的方式,减少访问磁盘的次数;
3)将 CLOB 和 BLOB 分别放置在不同的表空间上,并且将表空间分布在在多个磁盘上,获得最佳的磁盘访问速度。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)