五、上傳影像並使用ASP.NET 2.0資料
來源控制碼儲存二進位資料儘管ADO.NET方法運作在一個ASP.NET 2.0應用程式環境下,但是,你也能夠使用ASP.NET 2.0的資料來源控制項來把二進位資料儲存到一個資料庫,這不要求你寫ADO.NET程式碼。在這個示範程式中所使用的SqlDataSource控制項包含了一個InsertCommand,以及對應於Title,MIMEType和ImageData值的參數:
<asp:SqlDataSource ID="UploadPictureDataSource" runat="server"
ConnectionString="..."
InsertCommand="INSERT INTO [Pictures] ([Title], [MIMEType], [ImageData]) VALUES (@Title, @MIMEType, @ImageData)">
<InsertParameters>
<asp:Parameter Name="Title" Type="String" />
<asp:Parameter Name="MIMEType" Type="String" />
<asp:Parameter Name="ImageData" />
</InsertParameters>
</asp:SqlDataSource>
請注意,在此,ImageData參數並沒有指定一個類型。如果你試著使用GUI精靈來建構SqlDataSource的語法,那麼,它可能會給它指定Type="Object",然而,這個Type="Object"將會產生一個sql_variant類型的參數。然而,該sql_variants類型不能用來儲存影像或varbinary(MAX)資料類型,因為該sql_variant的內在資料大小不能超過8,000 個位元組。 (如果你試圖使用Type="Object",然後試圖保存超過8,000位元組大小的二進位數據,那麼,系統將拋出一個異常並顯示訊息"Parameter '@ImageData' exceeds the size limit for the sql_variant datatype ";如果你試圖添加不到8,000位元組大小的二進位數據,那麼,該異常將顯示訊息"Implicit conversion from data type sql_variant to varbinary(max) is not allowed")。
另外, DetailsView控制項包含了兩個TemplateField。其中,一個TemplateField中使用一個TextBox控制項來顯示標題列;另一個使用一個FileUpload控制項來表示ImageData列。最終結果是得到一個看起來類似於在"上傳圖像並使用ADO.NET程式碼儲存二進位資料"一節中的使用者介面。當點擊DetailsView的"Insert"按鈕時,它的Inserting事件激發,這時二進位資料必須從FileUpload控制項中取得,讀到一個位元組數組中,並且賦值給適當的參數:
Protected Sub UploadPictureUI_ItemInserting(ByVal sender As Object , ByVal e As System.Web.UI.WebControls.DetailsViewInsertEventArgs) Handles UploadPictureUI.ItemInserting
'引用FileUpload控制項Dim UploadedFile As FileUpload = CType(UploadPictureUI.FindControl("UploadedFile"),FileUpload)
'確保已經成功上傳一個檔案If UploadedFile.PostedFile Is Nothing OrElse String.IsNullOrstedEmpty(UploadedFile.Postedmloaded) .InputStream Is Nothing Then
....顯示錯誤訊息...
e.Cancel = True
Exit Sub
End If
'確保我們在處理一個JPG或GIF文件
Dim extension As String = Path.GetExtension(UploadedFile.PostedFile.FileName).ToLower()
Dim MIMEType As String = Nothing
Select Case extension
Case ".gif"
MIMEType = "image/gif"
Case ".jpg", ".jpeg", ".jpe"
MIMEType = "image/jpeg"
Case ".png"
MIMEType = "image/png"
Case Else
'無效檔案類型上載... 顯示錯誤訊息...
e.Cancel = True
Exit Sub
End Select
"指定MIMEType和ImageData參數的值
e.Values("MIMEType") = MIMEType
'把FileUpload的InputStream載入進字節數組中
Dim imageBytes(UploadedFile.PostedFile.InputStream.Length) As Byte
UploadedFile.PostedFile.InputStream.Read(imageBytes, 0, imageBytes.Length)
e.Values("ImageData") = imageBytes
End Sub
就像前面的"Insert"按鈕的Click事件處理器一樣,該DetailsView的Inserting事件處理器也執行相同的邏輯-只有一些小的語法差異。首先,既然FileUpload控制項位於一個範本內,所以,必須使用FindControl("controlID")方法以程式設計方式來引用它。一旦對它進行了引用,即對之進行相同的檢查以確保一個檔案被成功上傳,並且允許相應的副檔名。對於DetailsView的Inserting事件處理器存在一個微小的區別是,如果出現了錯誤,那麼,我們需要通知該DetailsView停止相應的插入工作-這是透過把e.Cancel屬性設定為True實現的。
檢查完之後,MIMEType和ImageData參數將會被使用e.Values("parameterName")=value語法進行賦值。就像在前面的ADO.NET範例中一樣,先把該二進位資料讀取到一個位元組數組中,然後把該位元組數組賦值給該參數。
六、 顯示二進位內容
無論你使用什麼技術把數據儲存在資料庫中,為了檢索並顯示二進位數據,我們需要建立一個新的ASP.NET頁面。這個名字為ShowPicture.aspx的頁面,將透過querystring把一個PictureID傳遞給它,並且從指定的產品的ImageData域中傳回該二進位資料。一旦完成,透過造訪/ShowPicture.aspx?PictureID=picutreID 位址即可看到一個特定的圖片。因此,為了把一個圖像顯示在一個web頁面上,我們可以使用一個圖像控制項並把它的ImageUrl屬性設定成適當的URL。
注意,這個ShowPicture.aspx在其.aspx頁面中並沒有包括任何HTML標記。在code-behind類別的Page_Load事件處理器中,將使用ADO.NET程式碼從資料庫擷取指定的Pictures行的MIMEType和ImageData。然後,該頁面的ContentType被設定為MIMEType域的值,並且使用Response.BinaryWrite(ImageData)輸出該二進位資料:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim PictureID As Integer = Convert.ToInt32(Request.QueryString("PictureID"))
'與資料庫連接並且傳回指定的圖片的圖片內容和MIME類型Using myConnection As New SqlConnection(ConfigurationManager.ConnectionStrings("ImageGalleryConnectionString").ConnectionString)
Const SQL As String = "SELECT [MIMEType], [ImageData] FROM [Pictures] WHERE [PictureID] = @PictureID"
Dim myCommand As New SqlCommand(SQL, myConnection)
myCommand.Parameters.AddWithValue("@PictureID", PictureID)
myConnection.Open()
Dim myReader As SqlDataReader = myCommand.ExecuteReader
If myReader.Read Then
Response.ContentType = myReader("MIMEType").ToString()
Response.BinaryWrite(myReader("ImageData"))
End If
myReader.Close()
myConnection.Close()
End Using
End Sub