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






2.54/5 (13投票s)
2004年6月30日
2分钟阅读

167798

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())
如果没有这些行,图像将直接流式传输到客户端并在浏览器中显示。