Sdílet prostřednictvím


Zobrazení binárních dat ve webových ovládacích prvcích dat (C#)

Scott Mitchell

Stáhnout PDF

V tomto kurzu se podíváme na možnosti prezentace binárních dat na webové stránce, včetně zobrazení souboru obrázku a zřízení odkazu Stáhnout pro soubor PDF.

Úvod

V předchozím kurzu jsme prozkoumali dvě techniky přidružení binárních dat k podkladovému datovému modelu aplikace a použili jsme ovládací prvek FileUpload k nahrání souborů z prohlížeče do systému souborů webového serveru. Zatím jsme zjistili, jak nahraná binární data přidružit k datovému modelu. To znamená, že po nahrání a uložení souboru do systému souborů musí být cesta k souboru uložena v příslušném záznamu databáze. Pokud jsou data uložena přímo v databázi, nemusí být nahraná binární data uložena do systému souborů, ale musí být vložena do databáze.

Než se ale podíváme na přidružení dat k datovému modelu, podívejme se nejprve na to, jak poskytnout binární data koncovému uživateli. Prezentace textových dat je dostatečně jednoduchá, ale jak by se měla prezentovat binární data? To samozřejmě závisí na typu binárních dat. U obrázků pravděpodobně chceme obrázek zobrazit; v případě souborů PDF, dokumentů Microsoft Word, souborů ZIP a dalších typů binárních dat je pravděpodobně vhodnější poskytnout odkaz Ke stažení.

V tomto kurzu se podíváme na to, jak prezentovat binární data spolu s přidruženými textovými daty pomocí webových ovládacích prvků dat, jako jsou GridView a DetailsView. V dalším kurzu se podíváme na přidružení nahraného souboru k databázi.

Krok 1: ZadáníBrochurePathhodnot

Sloupec Picture v tabulce Categories již obsahuje binární data pro různé obrázky kategorií. Konkrétně Picture sloupec pro každý záznam obsahuje binární obsah rastrového obrázku s nízkou kvalitou, 16 barev. Každý obrázek kategorie má šířku 172 pixelů a výšku 120 pixelů a spotřebuje přibližně 11 kB. A co víc, binární obsah ve Picture sloupci obsahuje 78 bajtů OLE hlavičku, která musí být odstraněna před zobrazením obrázku. Tyto informace o hlavičce jsou k dispozici, protože databáze Northwind má své kořeny v Aplikaci Microsoft Access. V Accessu se binární data ukládají pomocí datového typu objektu OLE, který se přichytá k této hlavičce. Prozatím uvidíme, jak z těchto obrázků v nízké kvalitě odebrat záhlaví, aby se obrázek zobrazil. V dalším kurzu vytvoříme rozhraní pro aktualizaci sloupce kategorie Picture a nahradíme tyto rastrové obrázky, které používají záhlaví OLE, ekvivalentními obrázky JPG bez zbytečných záhlaví OLE.

V předchozím kurzu jsme viděli, jak používat ovládací prvek FileUpload. Proto můžete pokračovat a přidat soubory brožur do systému souborů webového serveru. Tím se ale neaktualizuje BrochurePath sloupec v tabulce Categories . V dalším kurzu se dozvíme, jak toho dosáhnout, ale prozatím musíme hodnoty pro tento sloupec zadat ručně.

V tomto kurzu ke stažení najdete sedm souborů PDF brožury ve ~/Brochures složce, jeden pro každou z kategorií s výjimkou Seafood. Záměrně jsem vynechal přidání brožury Seafood, která ilustruje, jak zpracovat scénáře, kdy ne všechny záznamy mají přidružená binární data. Pokud chcete tabulku aktualizovat Categories pomocí těchto hodnot, klikněte pravým tlačítkem na uzel v Průzkumníku Categories serveru a zvolte Zobrazit data tabulky. Pak zadejte virtuální cesty k souborům brožury pro každou kategorii, která obsahuje brožuru, jak je znázorněno na obrázku 1. Vzhledem k tomu, že neexistuje žádná brožura pro kategorii Mořské plody, ponechte hodnotu sloupce BrochurePath jako NULL.

Ručně zadejte hodnoty sloupce Categories Table s BrožuraPath.

Obrázek 1: Ruční zadání hodnot pro Categories sloupec tabulky BrochurePath (kliknutím zobrazíte obrázek v plné velikosti)

BrochurePath S hodnotami zadanými pro Categories tabulku jsme připraveni vytvořit GridView, který uvádí každou kategorii spolu s odkazem ke stažení brožury kategorií. V kroku 4 rozšíříme toto zobrazení GridView tak, aby zobrazilo také obrázek kategorie.

Začněte přetažením objektu GridView ze sady nástrojů do Designer DisplayOrDownloadData.aspx stránky ve BinaryData složce. Nastavte GridView s ID na Categories a prostřednictvím inteligentní značky GridView s a zvolte jeho vazbu k novému zdroji dat. Konkrétně ho vytvořte vazbu na ObjectDataSource s názvem CategoriesDataSource , který načítá data pomocí CategoriesBLL metody object s GetCategories() .

Vytvoření nového objektuDataSource s názvem CategoriesDataSource

Obrázek 2: Vytvoření nového objektuDataSource s názvem CategoriesDataSource (kliknutím zobrazíte obrázek v plné velikosti)

Nakonfigurujte ObjectDataSource tak, aby používal třídu CategoriesBLL.

Obrázek 3: Konfigurace objektu ObjectDataSource pro použití CategoriesBLL třídy (kliknutím zobrazíte obrázek v plné velikosti)

Načtení seznamu kategorií pomocí metody GetCategories()

Obrázek 4: Načtení seznamu kategorií pomocí GetCategories() metody (kliknutím zobrazíte obrázek v plné velikosti)

Po dokončení průvodce Konfigurací zdroje dat visual Studio automaticky přidá BoundField do objektu Categories GridView pro CategoryIDobjekty , CategoryName, Description, NumberOfProductsa BrochurePathDataColumn s. Pokračujte a odeberte NumberOfProducts BoundField, protože GetCategories() dotaz metody s tyto informace nenačte. Odeberte CategoryID také BoundField a přejmenujte CategoryNameBrochurePath vlastnosti BoundFields HeaderText na Category (Kategorie) a Brožura (v uvedeném pořadí). Po provedení těchto změn by deklarativní značky GridView a ObjectDataSource měly vypadat takto:

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

Zobrazte tuto stránku v prohlížeči (viz Obrázek 5). Každá z osmi kategorií je uvedena. Sedm kategorií s BrochurePath hodnotami má hodnotu zobrazenou BrochurePath v příslušném BoundField. Mořské plody, které mají NULL hodnotu pro své BrochurePath, zobrazí prázdnou buňku.

Každý název kategorie, popis a hodnota Brožura jsou uvedené.

Obrázek 5: Název, popis a BrochurePath hodnota každé kategorie je uvedený (kliknutím zobrazíte obrázek v plné velikosti)

Místo zobrazení textu BrochurePath sloupce chceme vytvořit odkaz na brožuru. Chcete-li to provést, odeberte BrochurePath BoundField a nahraďte ho HyperLinkField. Nastavte novou vlastnost HyperLinkField na HeaderText Brožuru, její Text vlastnost na View Brožura a její DataNavigateUrlFields vlastnost na BrochurePath.

Přidání HyperLinkField pro BrožuruPath

Obrázek 6: Přidání hyperlinkfieldu pro BrochurePath

Tím přidáte sloupec odkazů do objektu GridView, jak je znázorněno na obrázku 7. Kliknutím na odkaz Zobrazit brožuru buď zobrazíte soubor PDF přímo v prohlížeči, nebo vyzvete uživatele ke stažení souboru v závislosti na tom, jestli je nainstalovaná čtečka PDF a nastavení prohlížeče.

Brožuru kategorie s lze zobrazit kliknutím na odkaz Zobrazit brožuru.

Obrázek 7: Brožuru kategorie s lze zobrazit kliknutím na odkaz Zobrazit brožuru (kliknutím zobrazíte obrázek v plné velikosti)

Zobrazí se pdf brožura kategorie s.

Obrázek 8: Zobrazí se pdf brožura kategorie s (kliknutím zobrazíte obrázek v plné velikosti)

Skrytí textu zobrazení brožury pro kategorie bez brožury

Jak ukazuje obrázek 7, BrochurePath HyperLinkField zobrazuje hodnotu vlastnosti Text (Zobrazit brožuru) pro všechny záznamy, bez ohledu na to, zda jeNULL pro BrochurePath. Samozřejmě, pokud BrochurePath je NULL, pak se odkaz zobrazí pouze jako text, stejně jako v případě kategorie Mořské plody (podívejte se zpět na obrázek 7). Místo zobrazení brožury s textem by mohlo být vhodné, aby tyto kategorie bez BrochurePath hodnoty zobrazovaly alternativní text, například Není k dispozici brožura.

Abychom mohli toto chování poskytnout, musíme použít TemplateField, jehož obsah je generován voláním metody stránky, která vygeneruje příslušný výstup na BrochurePath základě hodnoty. Tuto techniku formátování jsme poprvé prozkoumali v kurzu Používání polí šablon v ovládacím prvku GridView .

Převeďte HyperLinkField na TemplateField tak, že vyberete BrochurePath Pole HyperLinkField a potom kliknete na odkaz Převést toto pole na templatefield v dialogovém okně Upravit sloupce.

Převedení HyperLinkField na TemplateField

Obrázek 9: Převod HyperLinkField na TemplateField

Tím se vytvoří TemplateField s objektem ItemTemplate , který obsahuje webový ovládací prvek HyperLink, jehož NavigateUrl vlastnost je vázána na BrochurePath hodnotu. Nahraďte tento kód voláním metody GenerateBrochureLink, která předává hodnotu BrochurePath:

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

Dále vytvořte metodu protected ve třídě kódu na pozadí stránky ASP.NET s názvem GenerateBrochureLink , která vrací string a přijímá object jako vstupní parametr.

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

Tato metoda určuje, jestli je předávaná object hodnota databáze NULL , a pokud ano, vrátí zprávu oznamující, že v kategorii chybí brožura. Pokud existuje BrochurePath hodnota, zobrazí se v hypertextovém odkazu. Všimněte si, že pokud BrochurePath je hodnota k dispozici, předá se do ResolveUrl(url) metody. Tato metoda přeloží předanou adresu URL a nahradí ~ znak odpovídající virtuální cestou. Pokud je například aplikace rootovaná na adrese /Tutorial55, ResolveUrl("~/Brochures/Meats.pdf") vrátí se /Tutorial55/Brochures/Meat.pdf.

Obrázek 10 znázorňuje stránku po provedení těchto změn. Všimněte si, že v poli Seafood category (Mořské plody) BrochurePath se teď zobrazuje text No Brožura available (Není k dispozici žádná brožura).

Pro kategorie bez brožury se zobrazí text, který není k dispozici.

Obrázek 10: Pro kategorie bez brožury se zobrazí text bez brožury (kliknutím zobrazíte obrázek v plné velikosti)

Krok 3: Přidání webové stránky pro zobrazení obrázku kategorie

Když uživatel navštíví stránku ASP.NET, obdrží kód HTML stránky ASP.NET. Přijatý kód HTML je pouze text a neobsahuje žádná binární data. Veškerá další binární data, jako jsou obrázky, zvukové soubory, aplikace Macromedia Flash, vložená Přehrávač médií Windows videa atd., existují na webovém serveru jako samostatné prostředky. Kód HTML obsahuje odkazy na tyto soubory, ale neobsahuje skutečný obsah souborů.

Například v HTML se <img> element používá k odkazování na obrázek, přičemž src atribut odkazuje na soubor obrázku takto:

<img src="MyPicture.jpg" ... />

Když prohlížeč obdrží tento kód HTML, odešle webový server další požadavek na načtení binárního obsahu souboru obrázku, který pak zobrazí v prohlížeči. Stejný koncept platí pro všechna binární data. V kroku 2 nebyla brožura odeslána do prohlížeče jako součást kódu HTML stránky. Vykreslený kód HTML místo toho poskytoval hypertextové odkazy, které při kliknutí způsobily, že prohlížeč požádal o dokument PDF přímo.

Abychom uživatelům mohli zobrazit nebo umožnit stahování binárních dat, která se nacházejí v databázi, musíme vytvořit samostatnou webovou stránku, která vrátí data. Pro naši aplikaci je pouze jedno binární datové pole uložené přímo v databázi obrázku kategorie. Proto potřebujeme stránku, která při volání vrátí data obrázku pro určitou kategorii.

Přidejte novou stránku ASP.NET do BinaryData složky s názvem DisplayCategoryPicture.aspx. Přitom ponechte políčko Vybrat stránku předlohy nezaškrtnuté. Tato stránka očekává CategoryID hodnotu v řetězci dotazu a vrátí binární data sloupce dané kategorie Picture . Vzhledem k tomu, že tato stránka vrací binární data a nic jiného, nepotřebuje v oddílu HTML žádné značky. Proto klikněte na kartu Zdroj v levém dolním rohu a odeberte všechny značky stránky s s výjimkou direktivy <%@ Page %> . To znamená, DisplayCategoryPicture.aspx že deklarativní kód by se měl skládat z jednoho řádku:

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

Pokud se v direktivě MasterPageFile<%@ Page %> zobrazí atribut , odeberte ho.

Do třídy kódu na pozadí stránky přidejte do obslužné rutiny Page_Load události následující kód:

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

Tento kód začíná načtením CategoryID hodnoty řetězce dotazu do proměnné s názvem categoryID. Dále se data obrázku načtou prostřednictvím volání CategoriesBLL metody třídy s GetCategoryWithBinaryDataByCategoryID(categoryID) . Tato data jsou vrácena klientovi pomocí Response.BinaryWrite(data) metody , ale před zavoláním Picture je nutné odebrat záhlaví OLE hodnoty sloupce. Toho se dosáhne vytvořením byte pole s názvem strippedImageData , které bude obsahovat přesně o 78 znaků méně, než co je ve sloupci Picture . MetodaArray.Copy se používá ke zkopírování dat od category.Picture pozice 78 do strippedImageData.

Vlastnost Response.ContentType určuje typ MIME vráceného obsahu, aby prohlížeč věděl, jak ho vykreslit. Categories Vzhledem k tomu, že Picture sloupec tabulky je rastrový obrázek, použije se zde typ MIME rastrového obrázku (image/bmp). Pokud vynecháte typ MIME, většina prohlížečů bude i nadále zobrazovat obrázek správně, protože mohou typ odvodit na základě obsahu binárních dat souboru obrázku. Je však vhodné zahrnout typ MIME, pokud je to možné. Úplný seznam typů médií MIME najdete na webu autority pro přiřazená čísla v internetu.

Po vytvoření této stránky si můžete zobrazit konkrétní obrázek kategorie na adrese DisplayCategoryPicture.aspx?CategoryID=categoryID. Obrázek 11 znázorňuje obrázek kategorie Nápoje, který si můžete prohlédnout na stránce DisplayCategoryPicture.aspx?CategoryID=1.

Obrázek kategorie nápojů je zobrazen

Obrázek 11: Zobrazí se obrázek kategorie Nápoje (kliknutím zobrazíte obrázek v plné velikosti)

Pokud při návštěvě DisplayCategoryPicture.aspx?CategoryID=categoryIDnástroje dojde k výjimce s textem Nelze přetypovat objekt typu System.DBNull na typ System.Byte[], můžou to způsobovat dvě věci. Za prvé, Categories sloupec s Picture tabulky povoluje NULL hodnoty. Stránka DisplayCategoryPicture.aspx ale předpokládá, že existuje hodnota, která neníNULL . Vlastnost Picture objektu CategoriesDataTable nemůže být přímo přístupná, pokud má NULL hodnotu. Pokud chcete povolit NULL hodnoty pro Picture sloupec, měli byste zahrnout následující podmínku:

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

Výše uvedený kód předpokládá, že ve Images složce, kterou chcete zobrazit pro tyto kategorie bez obrázku, existuje soubor obrázku s názvem NoPictureAvailable.gif .

K této výjimce může dojít také v případě, že CategoriesTableAdapter se příkaz s metody SELECT s GetCategoryWithBinaryDataByCategoryID vrátil zpět na seznam sloupců hlavního dotazu, k čemuž může dojít, pokud používáte ad hoc příkazy SQL a znovu spustíte průvodce pro hlavní dotaz TableAdapter. Zkontrolujte, jestli GetCategoryWithBinaryDataByCategoryID příkaz metody SELECT s stále obsahuje Picture sloupec .

Poznámka

Při DisplayCategoryPicture.aspx každé návštěvě dojde k přístupu k databázi a vrátí se data obrázku zadané kategorie. Pokud se ale obrázek kategorie od posledního zobrazení uživatele nezměnil, je to zbytečné úsilí. Protokol HTTP naštěstí umožňuje podmíněné operace GET. Při podmíněném příkazu GET klient, který provádí požadavek HTTP, odesílá spolu s hlavičkouIf-Modified-Since PROTOKOLU HTTP, která poskytuje datum a čas, kdy klient naposledy načetl tento prostředek z webového serveru. Pokud se obsah od tohoto zadaného data nezměnil, webový server může odpovědět stavovým kódem 304(304) a neodeslat zpět obsah požadovaného prostředku. Stručně řečeno, tato technika zbavuje webový server nutnosti odesílat zpět obsah pro prostředek, pokud nebyl změněn od posledního přístupu klienta.

K implementaci tohoto chování ale musíte do tabulky přidat PictureLastModified sloupec, který zaznamená, kdy Picture byl sloupec naposledy aktualizován, a také kód pro kontrolu hlavičkyIf-Modified-Since.Categories Další informace o If-Modified-Since hlavičce a podmíněném pracovním postupu GET najdete v tématech PODMÍNĚNÝ PŘÍKAZ HTTP pro hackery RSS a Podrobnější pohled na provádění požadavků HTTP na stránce ASP.NET.

Krok 4: Zobrazení obrázků kategorií v GridView

Teď, když máme webovou stránku pro zobrazení konkrétního obrázku kategorie, můžeme ho zobrazit pomocí ovládacího prvku Obrázek webu nebo elementu HTML <img> odkazujícího na DisplayCategoryPicture.aspx?CategoryID=categoryID. Obrázky, jejichž adresa URL je určena databázová data lze zobrazit v GridView nebo DetailsView pomocí ImageField. ImageField obsahuje DataImageUrlField vlastnosti a DataImageUrlFormatString , které fungují stejně jako HyperLinkField DataNavigateUrlFields a DataNavigateUrlFormatString vlastnosti.

Pojďme rozšířit Categories GridView v o DisplayOrDownloadData.aspx přidání ImageField, aby se zobrazily obrázky jednotlivých kategorií. Jednoduše přidejte Pole ImageField a nastavte jeho DataImageUrlField vlastnosti a DataImageUrlFormatString na CategoryID a DisplayCategoryPicture.aspx?CategoryID={0}. Tím se vytvoří sloupec GridView, který vykreslí <img> prvek, jehož src atribut odkazuje na DisplayCategoryPicture.aspx?CategoryID={0}, kde {0} je nahrazen hodnotou GridView řádku s CategoryID .

Přidání pole ImageField do objektu GridView

Obrázek 12: Přidání ImageField do GridView

Po přidání ImageField by deklarativní syntaxe objektu GridView měla vypadat takto:

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

Chvíli se na tuto stránku podívejte v prohlížeči. Všimněte si, že každý záznam teď obsahuje obrázek kategorie.

Obrázek kategorie se zobrazí pro každý řádek.

Obrázek 13: Obrázek kategorie se zobrazí pro každý řádek (kliknutím zobrazíte obrázek v plné velikosti)

Souhrn

V tomto kurzu jsme se zabývali tím, jak prezentovat binární data. Způsob prezentace dat závisí na typu dat. Pro soubory brožur PDF jsme uživateli nabídli odkaz Zobrazit brožuru, který po kliknutí přenesl uživatele přímo do souboru PDF. Pro obrázek kategorie jsme nejprve vytvořili stránku pro načtení a vrácení binárních dat z databáze a pak jsme ji použili k zobrazení obrázků jednotlivých kategorií v objektu GridView.

Teď, když jsme se podívali na to, jak zobrazit binární data, jsme připraveni prozkoumat, jak provádět vkládání, aktualizace a odstraňování v databázi s binárními daty. V dalším kurzu se podíváme na to, jak přidružit nahraný soubor k odpovídajícímu záznamu databáze. V dalším kurzu se dozvíte, jak aktualizovat existující binární data a jak odstranit binární data při odebrání přidruženého záznamu.

Všechno nejlepší na programování!

O autorovi

Scott Mitchell, autor sedmi knih o ASP/ASP.NET a zakladatel 4GuysFromRolla.com, pracuje s webovými technologiemi Microsoftu od roku 1998. Scott pracuje jako nezávislý konzultant, školitel a spisovatel. Jeho nejnovější kniha je Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Můžete ho zastihnout na mitchell@4GuysFromRolla.comadrese . nebo prostřednictvím jeho blogu, který najdete na adrese http://ScottOnWriting.NET.

Zvláštní poděkování

Tato série kurzů byla zkontrolována mnoha užitečnými recenzenty. Hlavními recenzenty pro tento kurz byli Teresa Murphy a Dave Gardner. Chtěli byste si projít své nadcházející články na webu MSDN? Pokud ano, dejte mi řádek na mitchell@4GuysFromRolla.com.