亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

在ASP.NET 2.0中操作數(shù)據(jù)之五十三:在Data Web控件顯示二進(jìn)制數(shù)據(jù)

 更新時(shí)間:2016年05月17日 09:02:36   作者:heker2007  
本文主要介紹在ASP.NET 2.0中直接顯示PDF超鏈接的方法,以及如何把已二進(jìn)制數(shù)據(jù)形式保存的圖片顯示在GridView中的方法,雖然這種方法在實(shí)際開(kāi)發(fā)中很少用,但還是值得學(xué)習(xí)一下。

導(dǎo)言:

  在前面的教程我們闡述了應(yīng)用程序處理二進(jìn)制數(shù)據(jù)的2種模式,以及使用FileUpload 控件從瀏覽器向服務(wù)器文件系統(tǒng)上傳文件。當(dāng)文件上傳并存儲(chǔ)在文件系統(tǒng)里時(shí),應(yīng)在相應(yīng)的數(shù)據(jù)庫(kù)記錄里存儲(chǔ)該文件的存儲(chǔ)路徑。

  我們先來(lái)看如何為最終用戶(hù)提供二進(jìn)制數(shù)據(jù)。怎樣展示二進(jìn)制數(shù)據(jù)呢?這取決于其類(lèi)型。比如圖片,我們將其顯示為image;如果是PDFs,Microsoft Word文檔、ZIP文件或其它類(lèi)型的數(shù)據(jù),或許提供一個(gè)“Download”鏈接比較妥當(dāng)。

  在本節(jié),我們看如何在GridView和DetailsView一類(lèi)的數(shù)據(jù)Web控件里呈現(xiàn)二進(jìn)制數(shù)據(jù),在后面的教程我們將注意力轉(zhuǎn)向?qū)⑸蟼魑募蛿?shù)據(jù)庫(kù)聯(lián)系起來(lái)。

第一步:提供BrochurePath值

  表Categories的Picture列存儲(chǔ)相關(guān)類(lèi)的圖片信息。具體的講,為16色的低質(zhì)量位圖,大小為172乘120像素,約11 KB。另外還包括一個(gè)約78字節(jié)的OLE報(bào)頭,在顯示圖片的時(shí)候需要將其剝離。為什么會(huì)有報(bào)頭信息呢?因?yàn)閿?shù)據(jù)庫(kù)Northwind源于微軟的Access數(shù)據(jù)庫(kù)。在Access里二進(jìn)制數(shù)據(jù)OLE類(lèi)型來(lái)存儲(chǔ)的,該類(lèi)型會(huì)添加報(bào)頭?,F(xiàn)在,我們看如何從圖片剝離報(bào)頭,以便顯示。在后面的教程我們將創(chuàng)建一個(gè)界面,將帶報(bào)頭的這些位圖替換為不帶報(bào)頭的等價(jià)的JPG圖片。

  前面我們考察了如何使用FileUpload控件,讓我們繼續(xù)為服務(wù)器文件系統(tǒng)添加文件。不過(guò)暫時(shí)不用更新Categories表的BrochurePath列,那是下一章的內(nèi)容。我們現(xiàn)在需要手工為BrochurePath賦值。

  在本教程,當(dāng)你下載東西時(shí),可以看到在~/Brochures7文件夾有7個(gè)PDF小冊(cè)子,每個(gè)小冊(cè)子對(duì)應(yīng)一個(gè)種類(lèi),Seafood除外。我故意沒(méi)為Seafood提供PDF小冊(cè)子,以便探討如何處理某些記錄沒(méi)有附帶二進(jìn)制數(shù)據(jù)的情況。在服務(wù)器資源管理器里右鍵點(diǎn)擊Categories,選“查看表數(shù)據(jù)”,輸入文件路徑,如圖1所示。由于Seafood類(lèi)沒(méi)有圖片,將其BrochurePath的值設(shè)為“NULL”。 

http://img.jbzj.com/file_images/article/201605/201605170855051.gif
圖1:手工為表Categories的BrochurePath列鍵入值

第2步:在GridView里添加一個(gè)下載鏈接

  當(dāng)為表Categories的BrochurePath列賦值后,我們準(zhǔn)備創(chuàng)建一個(gè)GridView用于展示每個(gè)種類(lèi),并附帶一個(gè)鏈接下載每個(gè)類(lèi)的小冊(cè)子。在第4步我們將擴(kuò)展GridView以顯示每個(gè)類(lèi)的圖片。

  打開(kāi)BinaryData文件夾的DisplayOrDownloadData.aspx頁(yè)面并進(jìn)入設(shè)計(jì)模式,從工具箱里拖一個(gè)GridView控件到頁(yè)面,設(shè)其ID為Categories,從其智能標(biāo)簽選擇綁定到一個(gè)名為CategoriesDataSource的ObjectDataSource控件。該控件調(diào)用類(lèi)CategoriesBLL的GetCategories()方法。

http://img.jbzj.com/file_images/article/201605/201605170855052.gif
圖2:創(chuàng)建一個(gè)名為CategoriesDataSource的ObjectDataSource控件

http://img.jbzj.com/file_images/article/201605/201605170855053.gif
圖3:設(shè)置ObjectDataSource使用CategoriesBLL類(lèi)

http://img.jbzj.com/file_images/article/201605/201605170855054.gif
圖4:調(diào)用GetCategories()方法

  完成設(shè)置后,Visual Studio自動(dòng)的為CategoryID, CategoryName, Description, NumberOfProducts和BrochurePath生成BoundField。移除NumberOfProducts,因?yàn)镚etCategories()方法用不上,同樣將CategoryID移除了。分別把CategoryName和 BrochurePath的HeaderText屬性改為“Category”和“Brochure”。做上述修改后,你的GridView and ObjectDataSource的聲明代碼看起來(lái)應(yīng)該像下面的這樣:

<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>

  在瀏覽器查看該頁(yè)(如圖5)。列出了所有的8個(gè)類(lèi),除了Seafood,其它7個(gè)類(lèi)的BoundField列里顯示各自的BrochurePath值。由于Seafood的BrochurePath為NULL值,看起來(lái)為空格。

http://img.jbzj.com/file_images/article/201605/201605170855055.gif
圖5:顯示了每個(gè)類(lèi)別的Name, Description和BrochurePath值

  與其顯示BrochurePath的text值,不如創(chuàng)建一個(gè)指向小冊(cè)子的鏈接。移除BrochurePath,代之以HyperLinkField。設(shè)它的HeaderText屬性為“Brochure”,Text屬性為“View Brochure”, DataNavigateUrlFields屬性為“ BrochurePath”。

 

http://img.jbzj.com/file_images/article/201605/201605170855066.gif
圖6:添加一個(gè)指向BrochurePath的HyperLinkField

  這樣將在GridView里添加一列鏈接,如圖7所示。點(diǎn)“View Brochure”時(shí)要么直接在瀏覽器顯示PDF,要么提示用戶(hù)下載該文件。這取決于瀏覽器的設(shè)置以及是否安裝了PDF閱讀器。

http://img.jbzj.com/file_images/article/201605/201605170855067.gif
圖7:點(diǎn)擊“View Brochure”訪問(wèn)某類(lèi)的Brochure

http://img.jbzj.com/file_images/article/201605/201605170855068.gif
圖8:顯示某類(lèi)的PDF文件

隱藏?zé)o小冊(cè)子圖片的類(lèi)的“View Brochure” 文本

  如圖7所示,不管某個(gè)類(lèi)的BrochurePath是否為NULL值,名為BrochurePath的HyperLinkField都呈現(xiàn)為其Text屬性(“View Brochure”) 。當(dāng)然,如果BrochurePath為NULL值,鏈接只顯示為文本(而不帶下劃線),就像Seafood類(lèi)一樣(見(jiàn)圖7)。與顯示文本“View Brochure”相比,更為可取的是將那些BrochurePath值為空的類(lèi)顯示為“No Brochure Available”。

  為達(dá)此目的,我們需要用到TemplateField,使其產(chǎn)生一個(gè)基于BrochurePath值的合適的結(jié)果。我們先來(lái)看看如何實(shí)現(xiàn),就像在教程之12《在GridView控件中使用TemplateField》一樣。

  在“編輯列”對(duì)話框里選中名為BrochurePath的HyperLinkField,再點(diǎn)“Convert this field into a TemplateField”鏈接,將其轉(zhuǎn)換為T(mén)emplateField。 

http://img.jbzj.com/file_images/article/201605/201605170855069.gif
圖9:將HyperLinkField轉(zhuǎn)換為T(mén)emplateField

  這樣將創(chuàng)建一個(gè)TemplateField,其ItemTemplate模板包含一個(gè)HyperLink Web控件,該控件的NavigateUrl屬性為BrochurePath值。用下面的代碼將其替換掉:

<asp:TemplateField HeaderText="Brochure">
 <ItemTemplate>
 <%# GenerateBrochureLink(Eval("BrochurePath")) %>
 </ItemTemplate>
</asp:TemplateField>

  然后,在ASP.NET頁(yè)面的“后臺(tái)代碼”里添加一個(gè)protected類(lèi)型的GenerateBrochureLink方法,它接受一個(gè)輸入?yún)?shù)并返回一個(gè)字符串。

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()));
}

  該方法判斷傳入的值是否為NULL。如果是,則返回一個(gè)消息指出該類(lèi)沒(méi)有小冊(cè)子文件;相反,如果傳入值不為空,將顯示為一個(gè)鏈接。我們注意到,當(dāng)BrochurePath值不為空時(shí),將調(diào)用ResolveUrl(url)方法。該方法的作用在于將傳入的相對(duì)路徑轉(zhuǎn)換為物理路徑。比如應(yīng)用程序的根目錄在/Tutorial55,ResolveUrl("~/Brochures/Meats.pdf")返回的路徑是/Tutorial55/Brochures/Meat.pdf.

圖10為經(jīng)過(guò)上述修改后的界面。我們注意到Seafood類(lèi)的BrochurePath列現(xiàn)在顯示為文本“No Brochure Available”.

http://img.jbzj.com/file_images/article/201605/2016051708550610.gif
圖10:沒(méi)有小冊(cè)子的類(lèi)將顯示為文本“No Brochure Available”

第3步:新增頁(yè)面以顯示類(lèi)的圖片

  當(dāng)用戶(hù)訪問(wèn)一個(gè)ASP.NET頁(yè)面時(shí),他將接收該頁(yè)面的HTML代碼。HTML代碼僅僅包含了text文本,而并不包含任何的二進(jìn)制數(shù)據(jù)。任何的二進(jìn)制數(shù)據(jù),比如圖片,音樂(lè)文件、Flash程序、Windows Media Player視頻等,以獨(dú)立資源的形式存放于服務(wù)器。

  HTML只包含了這些文件的引用,并不包含這些文件本身。

  比如,在HTML里<img>元素用來(lái)引用一張圖片,其src屬性指向該圖片文件,如:
<img src="MyPicture.jpg" ... />

  當(dāng)瀏覽器收到HTML代碼時(shí),它向服務(wù)器發(fā)送獲取圖片的請(qǐng)求并將其顯示在瀏覽器中,該模式對(duì)所有的二進(jìn)制數(shù)據(jù)都適用。在第2步中,我們沒(méi)有在頁(yè)面的HTML標(biāo)記里將小冊(cè)子顯示在瀏覽器,而是在HTML標(biāo)記里提供一個(gè)超鏈接,當(dāng)點(diǎn)擊它是,導(dǎo)致瀏覽器直接請(qǐng)求PDF文件。

  為了顯示或允許用戶(hù)下載儲(chǔ)存在數(shù)據(jù)庫(kù)中的二進(jìn)制數(shù)據(jù),我們需要另外創(chuàng)建一個(gè)頁(yè)面,用于從數(shù)據(jù)庫(kù)返回所需的數(shù)據(jù)。對(duì)我們的應(yīng)用程序而言,由于直接存儲(chǔ)在數(shù)據(jù)庫(kù)中的二進(jìn)制數(shù)據(jù)只有一項(xiàng)——類(lèi)的圖片,所以我們需要一個(gè)頁(yè)面,當(dāng)需要時(shí)從數(shù)據(jù)庫(kù)返回某個(gè)特定類(lèi)的圖片。

  在BinaryData文件夾添加一個(gè)DisplayCategoryPicture.aspx頁(yè)面,注意不要使用母版頁(yè)。該頁(yè)面接受一個(gè)包含CategoryID值的查詢(xún)字符串,返回Picture列的二進(jìn)制數(shù)據(jù)。由于該頁(yè)只返回二進(jìn)制數(shù)據(jù),所以我們不需要頁(yè)面的HTML部分有任何代碼。進(jìn)入頁(yè)面的“源碼”模式,刪除頁(yè)面的所有代碼,只保留<%@ Page %>部分。也即:DisplayCategoryPicture.aspx頁(yè)面的聲明代碼應(yīng)該只由如下的單獨(dú)行構(gòu)成:

<%@ Page Language="C#" AutoEventWireup="true"
 CodeFile="DisplayCategoryPicture.aspx.cs"
 Inherits="BinaryData_DisplayCategoryPicture" %>

如果<%@ Page %>里包含有MasterPageFile屬性,將其刪除,同時(shí)在后臺(tái)代碼類(lèi)的Page_Load事件處理器里添加如下代碼:

protected void Page_Load(object sender, EventArgs e)
{
 int categoryID = Convert.ToInt32(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 first 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);
}

  代碼先讀取查詢(xún)字符串的CategoryID值,并對(duì)名為categoryID的變量賦值。然后,通過(guò)調(diào)用CategoriesBLL類(lèi)的
GetCategoryWithBinaryDataByCategoryID(categoryID)方法獲取圖片數(shù)據(jù),再通過(guò)Response.BinaryWrite(data)方法向客戶(hù)端返回?cái)?shù)據(jù)。不過(guò)在此之前先要?jiǎng)冸x數(shù)據(jù)的OLE報(bào)頭。怎么實(shí)現(xiàn)呢?創(chuàng)建一個(gè)名為strippedImageData的byte數(shù)組,它包含的字節(jié)剛好比Picture列的數(shù)據(jù)少78。而Array.Copy方法將從category.Picture的第78個(gè)字節(jié)開(kāi)始復(fù)制數(shù)據(jù)(即剛好剝離OLE報(bào)頭)。

  代碼中的Response.ContentType屬性指定了要返回內(nèi)容的MIME type,以便瀏覽器知道如何顯示數(shù)據(jù)。由于Categories表的Picture列存儲(chǔ)的是位圖圖片,故在這里,位圖圖片的MIME type是(image/bmp). 如果你忽視了MIME type,絕大多數(shù)瀏覽器也可以正確的顯示圖像,因?yàn)?,它們能根?jù)圖像文件的二進(jìn)制數(shù)據(jù)的內(nèi)容而推斷其類(lèi)型。即便如此,還是盡可能的使用MIME type。

創(chuàng)建頁(yè)面后,可以訪問(wèn)頁(yè)面

DisplayCategoryPicture.aspx?CategoryID=categoryID來(lái)查看某個(gè)特定類(lèi)的圖片。圖11顯示的是Beverages類(lèi)的圖片,頁(yè)面為
DisplayCategoryPicture.aspx?CategoryID=1.

http://img.jbzj.com/file_images/article/201605/2016051708550611.gif
圖11:顯示類(lèi)Beverages的圖片

  有時(shí)候,當(dāng)你訪問(wèn)DisplayCategoryPicture.aspx?CategoryID=categoryID頁(yè)面時(shí),有可能顯示這樣的提示:“Unable to cast object of type 'System.DBNull' to type 'System.Byte[]'”。原因有可能是如下2方面。第一,表Categories的Picture列允許為NULL值,而DisplayCategoryPicture.aspx page頁(yè)面總是假定傳入的為非NULL值。當(dāng)Picture為NULL值時(shí),不能直接訪問(wèn)CategoriesDataTable的Picture屬性。如果你允許Picture為NULL值,添加如下代碼:

if (category.IsPictureNull())
{
 // Display some "No Image Available" picture
 Response.Redirect("~/Images/NoPictureAvailable.gif");
}
else
{
 // Send back the binary contents of the Picture column
 // ... Set ContentType property and write out ...
 // ... data via Response.BinaryWrite ...
}

  上述代碼假定在Images文件夾里存在名為NoPictureAvailable.gif的圖片,當(dāng)某個(gè)類(lèi)沒(méi)有圖片時(shí),就顯示該圖片。

  另一種情況:當(dāng)你在向?qū)Ю镞x用“使用SQL語(yǔ)句”的模式再次運(yùn)行主查詢(xún)時(shí),它將影響GetCategoryWithBinaryDataByCategoryID方法的SELECT命令返回的列(換句話說(shuō),主查詢(xún)沒(méi)有返回Picture列,再次運(yùn)行主查詢(xún)時(shí)將使GetCategoryWithBinaryDataByCategoryID方法也不會(huì)返回Picture列)。所以,應(yīng)確保GetCategoryWithBinaryDataByCategoryID方法的SELECT命令返回Picture列。

  注意:每次訪問(wèn)DisplayCategoryPicture.aspx頁(yè)面時(shí),都會(huì)訪問(wèn)數(shù)據(jù)庫(kù)并返回所需的圖片。如果圖片自最近一次訪問(wèn)以來(lái)沒(méi)有改變過(guò)的話,這樣每次訪問(wèn)數(shù)據(jù)庫(kù)再返回?cái)?shù)據(jù)的做法效率是不高的。幸運(yùn)的是,HTTP允許使用conditional GETs,這樣的話,客戶(hù)端使HTTP請(qǐng)求發(fā)送一個(gè)If-Modified-Since HTTP header。If-Modified-Since HTTP header包含了客戶(hù)端最近一次從服務(wù)器獲取的數(shù)據(jù)以及時(shí)間。如果請(qǐng)求的內(nèi)容沒(méi)有發(fā)生改變,服務(wù)器響應(yīng)為Not Modified status code (304),并不返回請(qǐng)求的內(nèi)容。簡(jiǎn)而言之,如果請(qǐng)求的資源自最近一次訪問(wèn)以來(lái)沒(méi)發(fā)送改變的話,服務(wù)器將不會(huì)回傳該資源,以達(dá)到減輕服務(wù)器負(fù)荷的目的。

第四步:在GridView控件里顯示Category Pictures

  現(xiàn)在我們有一個(gè)web頁(yè)面來(lái)顯示某個(gè)特定種類(lèi)的圖片的。通過(guò)Image Web控件或 HTML <img>元素來(lái)指向DisplayCategoryPicture.aspx?CategoryID=categoryID頁(yè)面,從而達(dá)到顯示該圖片的目的。我們可以在GridView控件或DetailsView控件的 ImageField里顯示圖片。ImageField的DataImageUrlField屬性、DataImageUrlFormatString屬性與HyperLinkField的DataNavigateUrlFields屬性、DataNavigateUrlFormatString屬性用法相似。

  讓我們對(duì)DisplayOrDownloadData.aspx頁(yè)面里名為Categories的GridView控件進(jìn)行擴(kuò)充。添加一個(gè)ImageField,設(shè)其DataImageUrlField屬性為CategoryID;
DataImageUrlFormatString屬性為DisplayCategoryPicture.aspx?CategoryID={0}。這樣將為GridView增加一列,呈現(xiàn)為一個(gè)<img>元素,其src屬性為DisplayCategoryPicture.aspx?CategoryID={0},其中{0}將由GridView row的CategoryID值填充。

http://img.jbzj.com/file_images/article/201605/2016051708550612.gif
圖12:為GridView控件添加一個(gè)ImageField

添加完成后,你的GridView控件的聲明代碼看起來(lái)應(yīng)像下面這樣:

<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>

花幾分鐘在瀏覽器里查看該頁(yè)面,注意每一行記錄現(xiàn)在都包含一張?jiān)擃?lèi)的圖片。

http://img.jbzj.com/file_images/article/201605/2016051708550713.gif
圖13:每一行記錄都顯示一張圖片

總結(jié):

  在本節(jié)我們探討了如何顯示二進(jìn)制數(shù)據(jù),數(shù)據(jù)是如何呈現(xiàn)的取決于它的類(lèi)型。對(duì)PDF小冊(cè)子文件來(lái)說(shuō),我們提供了一個(gè)“View Brochure”鏈接,當(dāng)點(diǎn)擊它時(shí),直接將用戶(hù)指向PDF小冊(cè)子文件。對(duì)某個(gè)種類(lèi)的圖片,我們先是創(chuàng)建一個(gè)頁(yè)面來(lái)從數(shù)據(jù)庫(kù)獲取并顯示它,然后再在一個(gè)GridView控件里顯示圖片。既然看到了如何展示二進(jìn)制數(shù)據(jù),我們準(zhǔn)備探討如何對(duì)其展開(kāi)插入、更新、刪除操作。接下來(lái)的教程我們看如何將上傳文件和相應(yīng)的數(shù)據(jù)庫(kù)記錄聯(lián)系起來(lái)。然后,再探討如何更新現(xiàn)存的二進(jìn)制數(shù)據(jù),以及當(dāng)刪除數(shù)據(jù)庫(kù)記錄時(shí)如何刪除相應(yīng)的二進(jìn)制數(shù)據(jù)。

  祝編程快樂(lè)!

作者簡(jiǎn)介

  本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的書(shū),是4GuysFromRolla.com的創(chuàng)始人,自1998年以來(lái)一直應(yīng)用 微軟Web技術(shù)。大家可以點(diǎn)擊查看全部教程《[翻譯]Scott Mitchell 的ASP.NET 2.0數(shù)據(jù)教程》,希望對(duì)大家的學(xué)習(xí)ASP.NET有所幫助。

相關(guān)文章

最新評(píng)論