Introduction:
In the previous tutorial we described 2 patterns of application processing of binary data, and the use of FileUpload controls to upload files from the browser to the server file system. When the file is uploaded and stored in the file system, the storage path of the file should be stored in the corresponding database record.
Let's take a look at how to provide binary data to end users. How do i show binary data? This depends on its type. Like a picture, we display it as image, and if it's pdfs,microsoft Word documents, zip files, or other types of data, it might be appropriate to provide a "Download" link.
In this section, we look at how to render binary data in a data Web control such as GridView and DetailsView, and in the following tutorial we turn our attention to linking uploaded files to databases.
First step: Provide Brochurepath value
The picture column of the table categories stores pictures information about the related class. Specifically, a 16-color low quality bitmap with a size of 172 times 120 pixels, about one KB. Also included is an OLE header of about 78 bytes, which needs to be stripped when displaying the picture. Why does it have header information? Because the database Northwind originates from Microsoft's Access database. In Access, the binary data ole type is stored, and the type adds a header. Now, let's see how to split the header from the picture to display it. In the following tutorial we will create an interface to replace these bitmaps with headers with equivalent JPG images with no headers.
Before we examined how to use the FileUpload control, let's continue adding files to the server file system. However, it is not necessary to update the Brochurepath column of the Categories table for the time being, which is the content of the next chapter. We now need to manually assign values to Brochurepath.
In this tutorial, when you download something, you can see that there are 7 PDF booklets in the ~/brochures7 folder, one for each booklet, except for seafood. I deliberately did not provide a PDF brochure for seafood to explore how to handle situations where some records do not have binary data attached to them. Right-click Categories in Server Explorer, select "View table Data" and enter the file path, as shown in Figure 1. Because the seafood class does not have a picture, set its Brochurepath value to "NULL."
Figure 1: Type the value manually for the Brochurepath column of the table categories
Step 2nd: Add a download link to the GridView
After assigning a value to the Brochurepath column of the table categories, we're going to create a GridView to show each category, with a link to download each class brochure. In step 4th we extend the GridView to display pictures of each class.
Open the Displayordownloaddata.aspx page of the BinaryData folder and enter design mode, drag a GridView control from the toolbox to the page, set its ID to categories, and bind from its smart tag selection to a named Categoriesdataso The Urce ObjectDataSource Control. The control invokes the GetCategories () method of the class CATEGORIESBLL.
Figure 2: Creating a ObjectDataSource control named Categoriesdatasource
Figure 3: Setting up ObjectDataSource using the CATEGORIESBLL class
Figure 4: Calling the GetCategories () method
When Setup is complete, Visual Studio automatically generates Brochurepath for CategoryID, CategoryName, Description, Numberofproducts, and BoundField. Removes the numberofproducts because the GetCategories () method is not used, and the CategoryID is removed. Change the HeaderText property of CategoryName and Brochurepath to "Category" and "brochure" respectively. After making the above changes, your declaration code for the GridView and ObjectDataSource should look like the following:
<asp:gridview id= "Categories" runat= "Server"
autogeneratecolumns= "False" datakeynames= "CategoryID
" Datasourceid= "Categoriesdatasource" enableviewstate= "False" >
<Columns>
<asp:boundfield Datafield= "CategoryName" headertext= "Category" sortexpression= "CategoryName
"/>
<asp:boundfield Datafield= "Description" headertext= "Description" sortexpression= "Description
"/>
<asp:boundfield Datafield= "Brochurepath" headertext= "brochure" sortexpression= "Brochurepath
"/>
</Columns>
</asp:GridView>
<asp:objectdatasource id= "Categoriesdatasource" runat= "Server"
oldvaluesparameterformatstring= "original_{0}"
selectmethod= "getcategories" typename= "CategoriesBLL" >
</asp:ObjectDataSource>
View the page in the browser (Figure 5). All 8 classes are listed except seafood, and the BoundField columns of the other 7 classes display their respective Brochurepath values. Because Seafood's brochurepath is a null value, it appears to be a space.
Figure 5: Displays the name, description, and Brochurepath values for each category
Instead of displaying the Brochurepath text value, create a link to the booklet. Remove Brochurepath and replace it with HyperLinkField. Set its HeaderText property to "brochure", the Text property is "View brochure", and the DataNavigateUrlFields property is "Brochurepath".
Figure 6: Add a HyperLinkField pointing to Brochurepath
This will add a column of links to the GridView, as shown in Figure 7. Point "View brochure" either displays the PDF directly in the browser or prompts the user to download the file. This depends on your browser's settings and whether you have a PDF reader installed.
Figure 7: Click "View Brochure" to access a class of brochure
Figure 8: Displaying a PDF file for a class
Hide the "View brochure" text of a class without a booklet picture
As shown in Figure 7, the HyperLinkField named Brochurepath is rendered as its Text property ("View brochure"), regardless of whether the brochurepath of a class is a null value. Of course, if Brochurepath is a null value, the link is displayed as text (not underlined), just like the seafood class (see Figure 7). As opposed to displaying the text "View brochure", it is preferable to display those classes that have Brochurepath values empty as "No brochure Available".
To achieve this, we need to use TemplateField to produce an appropriate result based on the Brochurepath value. Let's take a look at how to do this, as in tutorial 12, "Using TemplateField in the GridView control."
In the Edit Column dialog box, select the HyperLinkField named Brochurepath, and then click the Convert this field into a TemplateField link to convert it to TemplateField.
Figure 9: Converting HyperLinkField to TemplateField
This creates a TemplateField whose ItemTemplate template contains a hyperlink Web control whose NavigateUrl property is the Brochurepath value. Replace it with the following code:
<asp:templatefield headertext= "Brochure" >
<ItemTemplate>
<%# generatebrochurelink (Eval (" Brochurepath "))%>
</ItemTemplate>
</asp:TemplateField>
Then, add a protected type Generatebrochurelink method to the ASP.net page's "Background Code", which takes an input parameter and returns a string.
Protected string Generatebrochurelink (object Brochurepath)
{
if (Convert.isdbnull (Brochurepath))
Return "No brochure Available";
else return
string. Format (@ "<a href=" "{0}" ">view brochure</a>",
ResolveUrl (brochurepath.tostring ()));
This method determines whether the passed-in value is null. If it is, a message is returned stating that the class does not have a brochure file, and conversely, if the incoming value is not empty, it will appear as a link. We note that the ResolveUrl (URL) method is invoked when the Brochurepath value is not empty. The purpose of this method is to convert an incoming relative path to a physical path. For example, the path that the application's root directory returns in/tutorial55,resolveurl ("~/brochures/meats.pdf") is/tutorial55/brochures/meat.pdf.
Figure 10 is the modified interface as described above. We note that the Brochurepath column for the Seafood class is now displayed as the text "No brochure Available".
Figure 10: Classes without brochures will be displayed as text "No brochure Available"
3rd Step: Add a page to display a picture of the class
When a user accesses a ASP.net page, he receives the HTML code for the page. The HTML code only contains text text and does not contain any binary data. Any binary data, such as pictures, music files, flash programs, and Windows Media player videos, are stored as separate resources on the server.
HTML contains only references to these files and does not contain the files themselves.
For example, in HTML elements are used to refer to a picture whose SRC attribute points to the picture file, such as:
When the browser receives the HTML code, it sends a request to the server to get the picture and displays it in the browser, which applies to all binary data. In step 2nd, we didn't display the brochure in the browser in the HTML tag of the page, but instead provided a hyperlink in the HTML tag, which, when clicked, caused the browser to request the PDF file directly.
To show or allow the user to download binary data stored in the database, we need to create a separate page to return the required data from the database. For our applications, because there is only one binary data stored directly in the database-a picture of the class-we need a page that returns a picture of a particular class from the database when needed.
Add a displaycategorypicture.aspx page to the BinaryData folder, and be careful not to use the master page. The page accepts a query string that contains the CategoryID value, and returns the binary data for the picture column. Because the page only returns binary data, we don't need any code in the HTML section of the page. Enter the "source" mode of the page, delete all the code of the page, only keep the <%@ page%> part. That is, the declaration code for the Displaycategorypicture.aspx page should consist of only the following separate lines:
<%@ Page language= "C #" autoeventwireup= true "
codefile=" DisplayCategoryPicture.aspx.cs "
inherits=" Binarydata_displaycategorypicture "%>
If the <%@ Page%> contains the MasterPageFile attribute, delete it, and add the following code in the Page_Load event handler of the background code class:
protected void Page_Load (object sender, EventArgs e) {int CategoryID = Convert.toint
(request.querystring["CategoryID"]);
Get information about the specified category Categoriesbll Categoryapi = new CATEGORIESBLL ();
northwind.categoriesdatatable categories = Categoryapi.getcategorywithbinarydatabycategoryid (CategoryID);
Northwind.categoriesrow category = Categories[0];
Output HTTP headers Providing information about the binary data Response.ContentType = "Image/bmp";
Output the binary data//But we need to strip out the OLE header const int oleheaderlength = 78; int strippedimagelength = category.
Picture.length-oleheaderlength;
byte[] Strippedimagedata = new Byte[strippedimagelength]; Array.copy (category.
Picture, Oleheaderlength, Strippedimagedata, 0, strippedimagelength);
Response.BinaryWrite (Strippedimagedata); }
The code first reads the CategoryID value of the query string and assigns a value to the variable named CategoryID. Then, by calling the Categoriesbll class's
The Getcategorywithbinarydatabycategoryid (CategoryID) method obtains the picture data and then returns the data to the client via the Response.BinaryWrite (the data) method. Before you do this, however, the OLE header of the data is stripped. How to achieve it? Create a byte array named Strippedimagedata that contains exactly 78 less than the data in the picture column. The Array.copy method will copy the data from the 78th byte of the category.picture (that is, just split the OLE header).
The Response.ContentType property in the code specifies the MIME type of the content to be returned so that the browser knows how to display the data. Because the picture column of the Categories table stores bitmap images, the MIME type of the bitmap picture is (image/bmp). If you ignore MIME types, most browsers can also display images correctly, because they can infer their type based on the contents of the binary data of the image file. Even so, use the MIME type as much as possible.
After you create a page, you can access the page
Displaycategorypicture.aspx? Categoryid=categoryid to view a picture of a particular class. Figure 11 shows a picture of the beverages class, and the page is
Displaycategorypicture.aspx? Categoryid=1.
Figure 11: Picture showing the class beverages
Sometimes, when you visit displaycategorypicture.aspx? When Categoryid=categoryid a page, it is possible to display such a hint: "Unable to cast object of type ' System.DBNull ' to type ' system.byte[] '". The reason may be as follows 2. First, the picture column of the table categories is allowed to be a null value, whereas the Displaycategorypicture.aspx page page always assumes that the passed-in value is not null. When the picture is a null value, you cannot directly access the Categoriesdatatable Picture property. If you allow the picture to be a null value, add the following code:
if (category. Ispicturenull ())
{
//Display some "No Image Available" Picture
Response.Redirect ("~/images/ Nopictureavailable.gif ");
}
else
{
//Send back the binary contents to the Picture column
//... Set ContentType property and write out ...
... data via Response.BinaryWrite ...
}
The code above assumes that a picture named Nopictureavailable.gif exists in the Images folder, and the picture is displayed when a class has no pictures.
Another scenario: When you run the main query again in the wizard using SQL statements, it affects the columns returned by the Select command of the Getcategorywithbinarydatabycategoryid method (in other words, The main query does not return the picture column, and when you run the main query again, the Getcategorywithbinarydatabycategoryid method does not return the picture column. Therefore, you should ensure that the Select command for the Getcategorywithbinarydatabycategoryid method returns the picture column.
Note: Each time you visit the displaycategorypicture.aspx page, you will access the database and return the pictures you want. If the picture has not changed since the most recent visit, it is not efficient to return data each time you access the database. Fortunately, HTTP allows conditional GETs to be used, so that the client sends an HTTP request to a if-modified-since HTTP header. The If-modified-since HTTP header contains the data and time that the client obtained most recently from the server. If the requested content has not changed, the server responds to not Modified status code (304) and does not return the requested content. In short, if the requested resource does not send a change since the most recent visit, the server will not return the resource for the purpose of mitigating the server load.
Step Fourth: Display category Pictures in the GridView control
Now we have a Web page to display a particular kind of picture. Point to Displaycategorypicture.aspx by Image Web control or HTML element? Categoryid=categoryid the page to display the image. We can display the picture in the ImageField of the GridView control or the DetailsView control. ImageField Dataimageurlfield Properties, dataimageurlformatstring properties, and HyperLinkField DataNavigateUrlFields properties, Datanavigateurlformatstring property usage is similar.
Let's extend the GridView control named categories in the Displayordownloaddata.aspx page. Add a ImageField, set its Dataimageurlfield property to CategoryID;
Dataimageurlformatstring property is Displaycategorypicture.aspx? Categoryid={0}. This will add a column for the GridView, rendering it as a element whose src attribute is displaycategorypicture.aspx? Categoryid={0}, where {0} will be populated by the CategoryID value of the GridView row.
Figure 12: Adding a ImageField for the GridView control
After the addition is complete, your GridView control's declaration code should look like the following:
<asp:gridview id= "Categories" runat= "Server" autogeneratecolumns= "False"
datakeynames= "CategoryID" Datasourceid= "Categoriesdatasource"
enableviewstate= "False" >
<Columns>
<asp:boundfield Datafield= "CategoryName" headertext= "Category" sortexpression= "CategoryName
"/>
<asp:boundfield Datafield= "Description" headertext= "Description" sortexpression= "Description"/> <asp
: TemplateField headertext= "Brochure" >
<ItemTemplate>
<%# generatebrochurelink (Eval (" Brochurepath "))%>
</ItemTemplate>
</asp:TemplateField>
<asp:imagefield Dataimageurlfield= "CategoryID"
dataimageurlformatstring= "displaycategorypicture.aspx?" categoryid={0} ">
</asp:ImageField>
</Columns>
</asp:GridView>
Take a few minutes to view the page in your browser, and note that each line of records now contains a picture of the class.
Figure 13: A picture is displayed for each row of records
Summarize:
In this section we explore how to display binary data, and how the data is rendered depends on its type. For the PDF brochure file, we provide a "View brochure" link that, when clicked, directly points the user to the PDF brochure file. For a particular kind of picture, we first create a page to fetch and display it from the database, and then display the picture in a GridView control. Now that we've seen how to present binary data, we're going to explore how to expand Inserts, updates, and deletes. The next tutorial is to see how to relate the uploaded files to the corresponding database records. Then explore how to update existing binary data and how to delete the corresponding binary data when you delete the database records.
I wish you a happy programming!
Author Introduction
Scott Mitchell, author of this series of tutorials, has six asp/asp. NET book, is the founder of 4GuysFromRolla.com, has been applying Microsoft Web technology since 1998. You can click to see all Tutorials "[translation]scott Mitchell asp.net 2.0 data tutorial," I hope to learn asp.net help.