二进制读写图片操作

我们在软件开发中,有相当多的时间花费在如何在UI中显示一些图片。通常,开发人员把图片存储到某个图片文件夹内,然后按要求显示它们。做这项工作,我们需要把图片路径存储到数据库中,而真正的图片文件存储到某个文件夹内。这样我们可以有效的减少数据库的大小,但是这样做将导致大量的磁盘空间被图片文件占用,也使得这些图片可以被轻易的访问到。

让我们来看一个解决方案。在接下来要介绍的代码中我们将知道如何把一个图片文件直接的存储到数据库中,而不是放到磁盘上的某个文件夹里。有一些解决方案使用的是.net和sqlserver数据库,这样就可以使用存储过程了。


摘要
从这段代码中我们将知道如何把一个图片格式的文件存储到数据库中而不是存储在某文件夹的物理路径中。
开发环境为在vs2005(website)中测试的;数据库用的是sqlserver
vs2005(c#,website)+sqlserver


//保存到数据库
protected void btnSave_Click(object sender, EventArgs e)
    {
        // 上传的图片文件到Image
        System.Drawing.Image img = System.Drawing.Image.FromFile(fileImg.PostedFile.FileName);

        // 以Jpeg格式存到内存中
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);

        using (SqlConnection con = new SqlConnection("server=.;database=test;uid=sa;"))
        {
            SqlCommand cmd = new SqlCommand("spInsertImage", con);
            cmd.CommandType = CommandType.StoredProcedure;

            cmd.Parameters.Add("@ImageBinary", System.Data.SqlDbType.Image);
            // 图片的二进制数据
            cmd.Parameters["@ImageBinary"].Value = ms.ToArray();

            con.Open();
            try
            {
                // 调存储过程
                cmd.ExecuteNonQuery();
                Response.Write("ok");
            }
            catch
            {
                Response.Write("error");
            }
        }

        img.Dispose();
        ms.Dispose();
        ms.Flush();


    }
分析
上面这段代码实际上是将图片文件插入到数据库中,接下来我将对这段代码做一些说明。

你能看到变量“sInsertQuery”的初始值是“insert into images([image]) VALUES(?).”,
这是因为我们不能知道完整的查询语句。我们需要增加一个二进制参数,这个参数的值为图片文件转换成二进制后的值。
(很明显,这个变量里不能增加这个参数)
因为这个原因,我们使用了一个占位符[?],它将被后来的参数“QueryParameter”代替。
因为需要创建一个二进制的OldDB参数,所以我们使用了FSO来创建。
当成功的创建了这个参数后,占为符[?]将被这个参数所代替并执行。

//读取
 public void InitData()
    {
        // 数据库中图片的ID绑定到一个DropDownList
        using (SqlConnection con = new SqlConnection("server=.;database=test;uid=sa;"))
        {
            SqlDataAdapter sda = new SqlDataAdapter("spSelectImage", con);

            DataSet ds = new DataSet();

            sda.Fill(ds);

            ddlImage.DataSource = ds;
            ddlImage.DataTextField = "ImageID";
            ddlImage.DataValueField = "ImageID";
            ddlImage.DataBind();

            ddlImage.Items.Insert(0, new ListItem("清选择", "0"));

            sda.Dispose();
        }
    }


    protected void ddlImage_SelectedIndexChanged(object sender, EventArgs e)
    {
        using (SqlConnection con = new SqlConnection("server=.;database=test;uid=sa;"))
        {
            SqlCommand cmd = new SqlCommand("spSelectImageById", con);
            cmd.CommandType = CommandType.StoredProcedure;

            cmd.Parameters.Add("@ImageID", SqlDbType.Int);
            // 在DropDownList中所选的ImageId
            cmd.Parameters["@ImageID"].Value = Int32.Parse(ddlImage.SelectedValue);

            con.Open();
            SqlDataReader sdr = cmd.ExecuteReader();

            Response.ClearContent();
            Response.ContentType = "image/jpeg";
            while (sdr.Read())
            {
                // 读出相应记录的二进制并送显
                Response.BinaryWrite((byte[])sdr[1]);
            }

            sdr.Close();
            sdr.Dispose();
        }

    }

以上代码实际上是从数据库中读取二进制数据,并在UI的picture box中显示成图片。接下来我们讨论一下上面的几行代码。
首先要导入System.IO命名空间以使用MemoryStream。
这里的“Connection()”是一个用户定义的类,它包含一个公共函数“doDBconnection()”。
这个公共函数拿到参数和数据库名字之后便执行并返回结果。

package { import flash.display.Bitmap; import flash.display.Loader; import flash.display.NativeMenu; import flash.display.NativeMenuItem; import flash.display.NativeWindow; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.filesystem.File; import flash.filesystem.FileMode; import flash.filesystem.FileStream; import flash.net.FileFilter; import flash.net.navigateToURL; import flash.net.URLRequest; import flash.utils.ByteArray; public class Main extends Sprite { private var rootMenu:NativeMenu = new NativeMenu; private var fileMenu:NativeMenu = new NativeMenu; private var openItem:NativeMenuItem = new NativeMenuItem("打开文件"); private var quitItem:NativeMenuItem = new NativeMenuItem("退出"); private var helpMenu:NativeMenu = new NativeMenu; private var fsnhf:NativeMenuItem = new NativeMenuItem("00"); private var window:NativeWindow = stage.nativeWindow; private var loader:Loader = new Loader; private var imageFileFilter:FileFilter = new FileFilter("图片(*.jpg;*.png;*.gif;*.jpeg)", "*.jpg;*.png;*.gif;*.jpeg"); public function Main():void { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; buildMenu(); configListeners(); } private function buildMenu():void { rootMenu.addSubmenu(fileMenu, "文件"); fileMenu.addItem(openItem); fileMenu.addItem(quitItem); rootMenu.addSubmenu(helpMenu, "帮助"); helpMenu.addItem(fsnhf); window.menu = rootMenu; } private function configListeners():void { openItem.addEventListener(Event.SELECT, eventHandler); quitItem.addEventListener(Event.SELECT, eventHandler); fsnhf.addEventListener(Event.SELECT, eventHandler); } private function eventHandler(event:Event):void { switch(event.target) { case openItem: var file:File = new File; file.addEventListener(Event.SELECT, selectFile); file.browseForOpen("打开文件", [imageFileFilter]); break; case quitItem: window.close(); break; case fsnhf: navigateToURL(new URLRequest("00")); break; } } private function selectFile(event:Event):void { var file:File = event.target as File; var stream:FileStream = new FileStream; stream.open(file, FileMode.READ); var bytes:ByteArray = new ByteArray; stream.readBytes(bytes, 0, stream.bytesAvailable); stream.close(); loader.unload(); loader = new Loader; loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded); loader.loadBytes(bytes); addChild(loader); } private function imageLoaded(event:Event):void { event.target.removeEventListener(Event.COMPLETE, imageLoaded); var bitmap:Bitmap = Bitmap(event.target.loader.content); window.width = bitmap.width; window.height = bitmap.height + 30; } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值