65.9K
CodeProject 正在变化。 阅读更多。
Home

从数据库二进制流式传输大型图像

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.54/5 (13投票s)

2004年6月30日

2分钟阅读

viewsIcon

167798

downloadIcon

2080

解释了如何对从数据库检索到的一个大图像进行绘制,然后使用“打开/保存”选项流式传输该图像。

引言

本文档解释了如何对从数据库检索到的一个大图像进行绘制操作,然后使用“打开/保存”选项在浏览器上流式传输该图像。

从数据库获取图像

对于此示例代码,我有一个数据库表ImageTable,其中包含一个名为Image的数据类型为image的列。

首先,我们需要从数据库中获取图像。由于我们需要对图像进行一些绘制,我们将图像转换为System.Drawing.Image。下面的函数将图像字节转换为System.Drawing.Image并返回它。

' This function returns the image retrieved from the database
Private Function GetImageFromDB(ByVal ImageID As Integer) As Image    
    Dim image As Image
    ...
    ...

    Try
        sqlCommand = "SELECT Image FROM ImageTable WHERE ImageID = "_
                     + ImageID.ToString()
        
        ...
               
        Dim dr As SqlDataReader
        dr = cmd.ExecuteReader()
        While (dr.Read())

            Dim byt As Byte()
            byt = dr.Item(strImage)
            ' Convert the image bytes to System.Drawing.Image
            Dim bmp As New Bitmap(New System.IO.MemoryStream(byt))
            image = bmp
                    
        End While
    
    ...
    
    End Try

    Return image

End Function

现在,我们需要使用此图像并在图像上执行绘制操作,然后将其作为二进制输出流式传输到浏览器。图像的检索方式如下:

Dim image As Image
image = GetImageFromDB(ImageID)

获取 Graphics 对象

为了对图像执行绘制操作,我们需要使用System.Drawing.Graphics类。如果数据库图像不是索引像素格式,可以直接从数据库图像获取Graphics对象。对于索引像素格式的图像,我们可以通过创建一个临时位图并将数据库图像复制到位图上来获取Graphics对象。执行此操作的代码如下所示:

Dim bmpNew As Bitmap
Dim imageNew As Image
Dim objGraphics As Graphics
Try
    objGraphics = Graphics.FromImage(image)               

Catch e As Exception
    ' The image is in indexed pixel format
    ' Create a temp bitmap

    bmpNew = New Bitmap(image.Width, image.Height)
    imageNew = bmpNew

    objGraphics = Graphics.FromImage(imageNew)

    ' Draw the contents of old bitmap to new bitmap
    objGraphics.DrawImage(image, New Rectangle(0, 0, _
                          imageNew.Width, imageNew.Height), _
                          0, 0, image.Width, image.Height, _
                          GraphicsUnit.Pixel)

    image = imageNew

End Try

在图像上绘制

这将从数据库中检索图像并创建一个Graphics对象。现在,对Graphics对象执行所有需要的绘制操作。例如,在图像上写入一些简单的文本..

Dim objFont As Font = New Font("Verdana", 12, FontStyle.Bold)
Dim objbrush As Brush = Brushes.Black
Dim rect As New Drawing.RectangleF(10, 10, 200, 50)
Dim objGraphics As Graphics
objGraphics.DrawString("Simple Text", objFont, objbrush, rect)

二进制流式传输

完成图像上的绘制操作后,我们将其流式传输到浏览器。对于小图像文件,简单的image.Save(Response.OutputStream, ImageFormat.Jpeg)就足够了。对于大文件(例如超过 1 MB),图像应以固定大小的块进行流式传输。

' Set the content type
Response.ContentType = "image/Jpeg"

Dim ms As MemoryStream = New MemoryStream()
image.Save(ms, Imaging.ImageFormat.Jpeg)
Dim bytImage(ms.Length) As Byte
bytImage = ms.ToArray()
ms.Close()

ms = New MemoryStream(bytImage)
Response.Clear()
Response.AddHeader("Content-Type", "binary/octet-stream")
Response.AddHeader("Content-Length", bytImage.Length.ToString())
Response.AddHeader("Content-Disposition", _
     "attachment; filename=DownloadedImage.jpg; size=" _
     + bytImage.Length.ToString())
Response.Flush()

Dim chunkSize As Integer = 1024

Dim i As Integer
For i = 0 To bytImage.Length Step chunkSize
    ' Everytime check to see if the browser is still connected
    If (Not Response.IsClientConnected) Then
        Exit For
    End If

    Dim size As Integer = chunkSize
    If (i + chunkSize >= bytImage.Length) Then
        size = (bytImage.Length - i)
    End If

    Dim chunk(size - 1) As Byte
    ms.Read(chunk, 0, size)
    Response.BinaryWrite(chunk)
    Response.Flush()
Next
ms.Close()

在这种情况下,我读取字节并以 1024 的大小流式传输它们。上面的代码最终会弹出一个带有“打开/保存”选项的“文件下载”对话框,用户可以选择从位置打开图像或将其保存到他的磁盘。这是通过以下行实现的:

Response.AddHeader("Content-Type", "binary/octet-stream")
Response.AddHeader("Content-Disposition", _
  "attachment; filename=DownloadedImage.jpg; size=" _
  + bytImage.Length.ToString())

如果没有这些行,图像将直接流式传输到客户端并在浏览器中显示。

© . All rights reserved.