5. Upload images and store binary data using ASP.NET 2.0 data source control code.
Although the ADO.NET method works in the context of an ASP.NET 2.0 application, you can also use ASP.NET 2.0 data source controls to store binary
data.Binary data is stored into a database, which does not require you to write ADO.NET code. The SqlDataSource control used in this demo program contains an InsertCommand and parameters corresponding to the Title, MIMEType, and ImageData values:
<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>
Note that here, the ImageData parameter does not specify a type. If you try to use the GUI wizard to build the syntax of a SqlDataSource, it will probably specify Type="Object" for it. However, this Type="Object" will produce a parameter of type sql_variant. However, the sql_variants type cannot be used to store images or varbinary (MAX) data types because the intrinsic data size of the sql_variant cannot exceed 8,000 bytes. (If you try to use Type="Object" and then try to save binary data that exceeds 8,000 bytes in size, the system will throw an exception with the message "Parameter '@ImageData' exceeds the size limit for the sql_variant datatype "; If you attempt to add binary data that is less than 8,000 bytes in size, the exception will display the message "Implicit conversion from data type sql_variant to varbinary(max) is not allowed").
In addition, the DetailsView control contains two TemplateFields. Among them, a TextBox control is used in one TemplateField to display the title bar; the other uses a FileUpload control to represent the ImageData bar. The end result is a user interface that looks similar to the one in the "Uploading images and storing binary data using ADO.NET code" section. When the "Insert" button of DetailsView is clicked, its Inserting event is fired. At this time, the binary data must be obtained from the FileUpload control, read into a byte array, and assigned to the appropriate parameters:
Protected Sub UploadPictureUI_ItemInserting(ByVal sender As Object , ByVal e As System.Web.UI.WebControls.DetailsViewInsertEventArgs) Handles UploadPictureUI.ItemInserting
'Reference the FileUpload control Dim UploadedFile As FileUpload = CType(UploadPictureUI.FindControl("UploadedFile"), FileUpload)
'Ensure that a file has been successfully uploadedIf UploadedFile.PostedFile Is Nothing OrElse String.IsNullOrEmpty(UploadedFile.PostedFile.FileName) OrElse UploadedFile.PostedFile .InputStream Is Nothing Then
...display error message...
e.Cancel = True
Exit Sub
End If
'Make sure we are dealing with a JPG or GIF file
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
'Invalid file type upload... error message displayed...
e.Cancel = True
Exit Sub
End Select
"Specify the values of the MIMEType and ImageData parameters
e.Values("MIMEType") = MIMEType
'Load the InputStream of FileUpload into the byte array
Dim imageBytes(UploadedFile.PostedFile.InputStream.Length) As Byte
UploadedFile.PostedFile.InputStream.Read(imageBytes, 0, imageBytes.Length)
e.Values("ImageData") = imageBytes
End Sub
Just like the previous "Insert" button's Click event handler, the DetailsView's Inserting event handler also performs the same logic - there are only some minor syntax differences. First, since the FileUpload control is inside a template, it must be referenced programmatically using the FindControl("controlID") method. Once it is referenced, the same checks are performed to ensure that a file was successfully uploaded and that the appropriate extension was allowed. A slight difference to the Inserting event handler of DetailsView is that if an error occurs, then we need to notify the DetailsView to stop the corresponding insertion work - this is achieved by setting the e.Cancel property to True.
After checking, the MIMEType and ImageData parameters will be assigned using the e.Values("parameterName")=value syntax. Just like in the previous ADO.NET example, first read the binary data into a byte array, and then assign the byte array to the parameter.
6. Display binary content
No matter what technology you use to store data in the database, in order to retrieve and display binary data, we need to create a new ASP.NET page. The page named ShowPicture.aspx will pass a PictureID to it through the querystring and return the binary data from the ImageData field of the specified product. Once completed, a specific picture can be seen by visiting the address /ShowPicture.aspx?PictureID=picutreID. Therefore, in order to display an image on a web page, we can use an image control and set its ImageUrl property to the appropriate URL.
Note that ShowPicture.aspx does not include any HTML tags in its .aspx page. In the Page_Load event handler of the code-behind class, ADO.NET code will be used to retrieve the MIMEType and ImageData of the specified Pictures row from the database. Then, the ContentType of the page is set to the value of the MIMEType field, and the binary data is output using 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"))
'Connect to the database and return the image content and MIME type of the specified picture 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