Partager via


Affichage de données binaires dans les contrôles web de données (C#)

par Scott Mitchell

Télécharger le PDF

Dans ce tutoriel, nous examinons les options permettant de présenter des données binaires sur une page Web, notamment l’affichage d’un fichier image et l’approvisionnement d’un lien « Télécharger » pour un fichier PDF.

Introduction

Dans le tutoriel précédent, nous avons exploré les deux techniques permettant d’associer des données binaires à un modèle de données sous-jacent d’une application et d’utiliser le contrôle FileUpload pour charger des fichiers à partir d’un navigateur vers le système de fichiers du serveur web. Nous avons encore vu comment associer les données binaires chargées au modèle de données. Autrement dit, une fois qu’un fichier a été chargé et enregistré dans le système de fichiers, un chemin d’accès au fichier doit être stocké dans l’enregistrement de base de données approprié. Si les données sont stockées directement dans la base de données, les données binaires chargées ne doivent pas être enregistrées dans le système de fichiers, mais doivent être injectées dans la base de données.

Avant d’examiner l’association des données au modèle de données, examinons d’abord comment fournir les données binaires à l’utilisateur final. La présentation des données de texte est assez simple, mais comment les données binaires doivent-elles être présentées ? Cela dépend bien entendu du type de données binaires. Pour les images, nous voulons probablement afficher l’image ; Pour les fichiers PDF, les documents Microsoft Word, les fichiers ZIP et d’autres types de données binaires, la fourniture d’un lien de téléchargement est probablement plus appropriée.

Dans ce tutoriel, nous allons examiner comment présenter les données binaires en même temps que ses données de texte associées à l’aide de contrôles Web de données tels que GridView et DetailsView. Dans le tutoriel suivant, nous allons attirer l’attention sur l’association d’un fichier chargé à la base de données.

Étape 1 : Fournir desBrochurePathvaleurs

La Picture colonne de la Categories table contient déjà des données binaires pour les différentes images de catégorie. Plus précisément, la Picture colonne de chaque enregistrement contient le contenu binaire d’une image bitmap de 16 couleurs de qualité, grainy. Chaque image de catégorie est de 172 pixels de large et de 120 pixels de hauteur et consomme environ 11 Ko. De plus, le contenu binaire de la Picture colonne inclut un en-tête OLE de 78 octets qui doit être supprimé avant d’afficher l’image. Ces informations d’en-tête sont présentes, car la base de données Northwind a ses racines dans Microsoft Access. Dans Access, les données binaires sont stockées à l’aide du type de données OLE Object, qui s’inscrit dans cet en-tête. Pour l’instant, nous allons voir comment supprimer les en-têtes de ces images de faible qualité afin d’afficher l’image. Dans un prochain tutoriel, nous allons créer une interface pour mettre à jour une colonne de Picture catégorie et remplacer ces images bitmap qui utilisent des en-têtes OLE avec des images JPG équivalentes sans les en-têtes OLE inutiles.

Dans le tutoriel précédent, nous avons vu comment utiliser le contrôle FileUpload. Par conséquent, vous pouvez aller de l’avant et ajouter des fichiers de brochure au système de fichiers du serveur web. Toutefois, cela ne met pas à jour la BrochurePath colonne dans la Categories table. Dans le tutoriel suivant, nous allons voir comment procéder, mais pour le moment, nous devons fournir manuellement des valeurs pour cette colonne.

Dans ce tutoriel, vous trouverez sept fichiers de brochure PDF dans le ~/Brochures dossier, un pour chacune des catégories à l’exception des fruits de mer. J’ai omis délibérément d’ajouter une brochure De fruits de mer pour illustrer comment gérer les scénarios où tous les enregistrements n’ont pas de données binaires associées. Pour mettre à jour la Categories table avec ces valeurs, cliquez avec le bouton droit sur le nœud à partir de l’Explorateur Categories de serveurs et choisissez Afficher les données de table. Ensuite, entrez les chemins d’accès virtuels aux fichiers de brochure pour chaque catégorie qui a une brochure, comme le montre la figure 1. Étant donné qu’il n’y a pas de brochure pour la catégorie Fruits de mer, laissez sa BrochurePath valeur de colonne comme NULL.

Entrez manuellement les valeurs de la colonne BrochurePath de la table Catégories

Figure 1 : Entrer manuellement les valeurs de la colonne de table Categories BrochurePath (cliquez pour afficher l’image de taille complète)

Avec les BrochurePath valeurs fournies pour la Categories table, nous sommes prêts à créer un GridView qui répertorie chaque catégorie, ainsi qu’un lien pour télécharger la brochure de catégorie. À l’étape 4, nous allons étendre ce GridView pour afficher également l’image de catégorie.

Commencez par faire glisser un GridView à partir de la boîte à outils vers le Concepteur de la DisplayOrDownloadData.aspx page dans le BinaryData dossier. Définissez les gridViews ID sur Categories et via la balise active gridView, choisissez de la lier à une nouvelle source de données. Plus précisément, liez-le à un ObjectDataSource nommé CategoriesDataSource qui récupère des données à l’aide de la méthode de l’objet CategoriesBLL GetCategories() .

Créer un objet ObjectDataSource nommé CategoriesDataSource

Figure 2 : Créer un ObjetDataSource nommé CategoriesDataSource (cliquez pour afficher l’image de taille complète)

Configurer ObjectDataSource pour utiliser la classe CategoriesBLL

Figure 3 : Configurer ObjectDataSource pour utiliser la classe (Cliquez pour afficher l’image CategoriesBLLde taille complète)

Récupérer la liste des catégories à l’aide de la méthode GetCategories()

Figure 4 : Récupérer la liste des catégories à l’aide de la GetCategories() méthode (Cliquez pour afficher l’image de taille complète)

Une fois l’Assistant Configuration de la source de données terminée, Visual Studio ajoute automatiquement un Objet BoundField à Categories GridView pour le gridView pour les CategoryIDéléments , CategoryName, DescriptionNumberOfProductset BrochurePath DataColumn s. Continuez et supprimez BoundField NumberOfProducts , car la requête de la GetCategories() méthode ne récupère pas ces informations. Supprimez également les propriétés BoundField et renommez les CategoryID CategoryName BrochurePath propriétés BoundFields HeaderText en Catégorie et Brochure, respectivement. Après avoir apporté ces modifications, votre balisage déclaratif GridView et ObjectDataSource doit ressembler à ce qui suit :

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

Affichez cette page via un navigateur (voir la figure 5). Chacune des huit catégories est répertoriée. Les sept catégories avec BrochurePath des valeurs ont la BrochurePath valeur affichée dans l’objet BoundField respectif. Fruits de mer, qui a une NULL valeur pour son BrochurePath, affiche une cellule vide.

Chaque nom, description et valeur brochurePath de chaque catégorie est listée

Figure 5 : Chaque nom, description et BrochurePath valeur de chaque catégorie est répertorié (cliquez pour afficher l’image de taille complète)

Au lieu d’afficher le texte de la BrochurePath colonne, nous voulons créer un lien vers la brochure. Pour ce faire, supprimez boundField BrochurePath et remplacez-le par un HyperLinkField. Définissez la nouvelle propriété HyperLinkField sur HeaderText Brochure, sa Text propriété sur View Brochure et sa DataNavigateUrlFields propriété BrochurePathsur .

Ajouter un HyperLinkField pour BrochurePath

Figure 6 : Ajouter un champ HyperLinkField pour BrochurePath

Cette opération ajoute une colonne de liens à GridView, comme l’illustre la figure 7. Le fait de cliquer sur un lien Afficher la brochure affiche le fichier PDF directement dans le navigateur ou invite l’utilisateur à télécharger le fichier, selon qu’un lecteur PDF est installé et que les paramètres du navigateur soient installés.

Une brochure de catégorie peut être consultée en cliquant sur le lien Afficher la brochure

Figure 7 : Une brochure de catégorie peut être consultée en cliquant sur le lien Afficher la brochure (cliquez pour afficher l’image pleine taille)

Le fichier PDF de la brochure de catégorie est affiché

Figure 8 : Le fichier PDF de la brochure de catégorie s’affiche (cliquez pour afficher l’image de taille complète)

Masquage du texte de la brochure pour les catégories sans brochure

Comme le montre la figure 7, l’HyperLinkField BrochurePath affiche sa Text valeur de propriété (Afficher la brochure) pour tous les enregistrements, qu’il y ait une valeur non-valeurNULL pour BrochurePath. Bien sûr, si BrochurePath c’est NULLle cas, le lien est affiché en tant que texte uniquement, comme c’est le cas avec la catégorie Fruits de mer (reportez-vous à la figure 7). Plutôt que d’afficher le texte Afficher la brochure, il peut être intéressant d’avoir ces catégories sans BrochurePath valeur afficher un texte de remplacement, comme Aucune brochure disponible.

Pour fournir ce comportement, nous devons utiliser un TemplateField dont le contenu est généré via un appel à une méthode de page qui émet la sortie appropriée en fonction de la BrochurePath valeur. Nous avons d’abord exploré cette technique de mise en forme dans le didacticiel Utilisation de TemplateFields dans le didacticiel Contrôle GridView.

Transformez HyperLinkField en modèleField en sélectionnant BrochurePath HyperLinkField, puis cliquez sur le lien Convertir ce champ en lien TemplateField dans la boîte de dialogue Modifier les colonnes.

Convertir HyperLinkField en un TemplateField

Figure 9 : Convertir HyperLinkField en un TemplateField

Cela crée un TemplateField avec un ItemTemplate contrôle Web HyperLink dont NavigateUrl la propriété est liée à la BrochurePath valeur. Remplacez ce balisage par un appel à la méthode GenerateBrochureLink, en passant la valeur de BrochurePath:

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

Ensuite, créez une protected méthode dans la classe code-behind de la page ASP.NET nommée GenerateBrochureLink qui retourne un string paramètre d’entrée et accepte un object paramètre d’entrée.

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

Cette méthode détermine si la valeur transmise object est une base de données NULL et, le cas échéant, retourne un message indiquant que la catégorie n’a pas de brochure. Sinon, s’il existe une BrochurePath valeur, elle s’affiche dans un lien hypertexte. Notez que si la BrochurePath valeur est présente, elle est passée dans la ResolveUrl(url) méthode. Cette méthode résout l’URL passée, en remplaçant le ~ caractère par le chemin d’accès virtuel approprié. Par exemple, si l’application est rooté à /Tutorial55, ResolveUrl("~/Brochures/Meats.pdf") retourne /Tutorial55/Brochures/Meat.pdf.

La figure 10 montre la page après l’application de ces modifications. Notez que le champ de la catégorie Fruits de BrochurePath mer affiche désormais le texte « Aucune brochure disponible ».

Le texte non disponible est affiché pour ces catégories sans brochure

Figure 10 : Le texte non disponible est affiché pour ces catégories sans brochure (cliquez pour afficher l’image pleine taille)

Étape 3 : Ajout d’une page web pour afficher une image de catégorie

Lorsqu’un utilisateur visite une page ASP.NET, il reçoit le code HTML de la page ASP.NET. Le code HTML reçu est simplement du texte et ne contient aucune donnée binaire. Toutes les données binaires supplémentaires, telles que les images, les fichiers audio, les applications Macromedia Flash, les vidéos incorporées Lecteur multimédia Windows, etc. existent sous forme de ressources distinctes sur le serveur web. Le code HTML contient des références à ces fichiers, mais n’inclut pas le contenu réel des fichiers.

Par exemple, en HTML, l’élément <img> est utilisé pour référencer une image, avec l’attribut src pointant vers le fichier image comme suit :

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

Lorsqu’un navigateur reçoit ce code HTML, il envoie une autre requête au serveur web pour récupérer le contenu binaire du fichier image, qu’il affiche ensuite dans le navigateur. Le même concept s’applique à toutes les données binaires. À l’étape 2, la brochure n’a pas été envoyée au navigateur dans le cadre du balisage HTML de la page. Au lieu de cela, le code HTML rendu fournit des liens hypertexte qui, en cas de clic, ont provoqué le navigateur pour demander directement le document PDF.

Pour afficher ou autoriser les utilisateurs à télécharger des données binaires qui résident dans la base de données, nous devons créer une page web distincte qui retourne les données. Pour notre application, il n’existe qu’un seul champ de données binaires stocké directement dans la base de données de l’image de catégorie. Par conséquent, nous avons besoin d’une page qui, lorsqu’elle est appelée, retourne les données d’image pour une catégorie particulière.

Ajoutez une nouvelle page ASP.NET au BinaryData dossier nommé DisplayCategoryPicture.aspx. Dans ce cas, laissez la case à cocher Sélectionner la page maître désactivée. Cette page attend une CategoryID valeur dans la chaîne de requête et retourne les données binaires de cette colonne de Picture catégorie. Étant donné que cette page retourne des données binaires et rien d’autre, elle n’a pas besoin de balisage dans la section HTML. Par conséquent, cliquez sur l’onglet Source dans le coin inférieur gauche et supprimez toutes les marques de la page à l’exception de la <%@ Page %> directive. Autrement dit, DisplayCategoryPicture.aspx le balisage déclaratif doit se composer d’une seule ligne :

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

Si vous voyez l’attribut MasterPageFile dans la <%@ Page %> directive, supprimez-le.

Dans la classe code-behind de la page, ajoutez le code suivant au Page_Load gestionnaire d’événements :

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

Ce code commence par lire dans la CategoryID valeur querystring dans une variable nommée categoryID. Ensuite, les données d’image sont récupérées via un appel à la CategoriesBLL méthode de GetCategoryWithBinaryDataByCategoryID(categoryID) classe. Ces données sont retournées au client à l’aide de la Response.BinaryWrite(data) méthode, mais avant d’être appelées, l’en-tête OLE de la Picture valeur de colonne doit être supprimé. Pour ce faire, créez un byte tableau nommé strippedImageData qui contiendra précisément 78 caractères inférieurs à ce qui se trouve dans la Picture colonne. La Array.Copy méthode est utilisée pour copier les données à partir de category.Picture la position 78 à strippedImageData.

La Response.ContentType propriété spécifie le type MIME du contenu retourné afin que le navigateur sache comment le restituer. Étant donné que la Categories colonne de Picture la table est une image bitmap, le type MIME bitmap est utilisé ici (image/bmp). Si vous omettez le type MIME, la plupart des navigateurs affichent toujours l’image correctement, car ils peuvent déduire le type en fonction du contenu des données binaires du fichier image. Toutefois, il est prudent d’inclure le type MIME dans la mesure du possible. Consultez le site web de l’Autorité des numéros attribués à Internet pour obtenir une liste complète des types de supports MIME.

Une fois cette page créée, une image de catégorie particulière peut être consultée en visitant DisplayCategoryPicture.aspx?CategoryID=categoryID. La figure 11 montre l’image de la catégorie Boissons, qui peut être vue à partir de DisplayCategoryPicture.aspx?CategoryID=1.

L’image de la catégorie boissons est affichée

Figure 11 : L’image de la catégorie boissons s’affiche (cliquez pour afficher l’image de taille complète)

Si, lors de la visite DisplayCategoryPicture.aspx?CategoryID=categoryID, vous obtenez une exception qui lit Impossible de convertir l’objet de type « System.DBNull » en type « System.Byte[] », il existe deux éléments susceptibles de provoquer cette erreur. Tout d’abord, la Categories colonne de la Picture table autorise les NULL valeurs. Toutefois, la DisplayCategoryPicture.aspx page suppose qu’il existe une valeur nonNULL présente. La Picture propriété de l’objet CategoriesDataTable ne peut pas être directement accessible s’il a une NULL valeur. Si vous souhaitez autoriser NULL les valeurs de la Picture colonne, vous souhaitez inclure la condition suivante :

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

Le code ci-dessus suppose qu’il existe un fichier image nommé NoPictureAvailable.gif dans le Images dossier que vous souhaitez afficher pour ces catégories sans image.

Cette exception peut également être provoquée si l’instruction CategoriesTableAdapter s GetCategoryWithBinaryDataByCategoryID method s est rétablie dans la liste de colonnes de SELECT la requête principale, ce qui peut se produire si vous utilisez des instructions SQL ad hoc et que vous avez réexécuté l’Assistant pour la requête principale de TableAdapter. Vérifiez que l’instruction GetCategoryWithBinaryDataByCategoryID de la SELECT méthode inclut toujours la Picture colonne.

Remarque

Chaque fois que l’objet DisplayCategoryPicture.aspx est visité, la base de données est accessible et les données d’image de catégorie spécifiées sont retournées. Si l’image de la catégorie n’a pas changé depuis que l’utilisateur l’a vue pour la dernière fois, cela est perdu. Heureusement, HTTP autorise les GET conditionnels. Avec un GET conditionnel, le client effectuant la requête HTTP envoie le long d’un If-Modified-Since en-tête HTTP qui fournit la date et l’heure de la dernière récupération de cette ressource à partir du serveur web. Si le contenu n’a pas changé depuis cette date spécifiée, le serveur web peut répondre avec un code d’état non modifié (304) et renvoyer le contenu de la ressource demandée. En bref, cette technique empêche le serveur web de devoir renvoyer du contenu pour une ressource s’il n’a pas été modifié depuis le dernier accès au client.

Toutefois, pour implémenter ce comportement, vous devez ajouter une PictureLastModified colonne à la Categories table pour capturer le moment de la dernière mise à jour de la Picture colonne, ainsi que le code pour rechercher l’en-tête If-Modified-Since . Pour plus d’informations sur l’en-tête et le If-Modified-Since flux de travail GET conditionnel, consultez HTTP Conditional GET for RSS Hackers and A Deeper Look at Performing HTTP Requests in an ASP.NET Page.

Étape 4 : Affichage des images de catégorie dans un GridView

Maintenant que nous avons une page web pour afficher une image de catégorie particulière, nous pouvons l’afficher à l’aide du contrôle Web Image ou d’un élément HTML <img> pointant vers DisplayCategoryPicture.aspx?CategoryID=categoryID. Les images dont l’URL est déterminée par les données de base de données peuvent être affichées dans GridView ou DetailsView à l’aide de ImageField. ImageField contient et propriétés DataImageUrlField qui fonctionnent comme les propriétés et DataNavigateUrlFormatString les propriétés HyperLinkFieldDataNavigateUrlFields.DataImageUrlFormatString

Nous allons augmenter Categories GridView en DisplayOrDownloadData.aspx ajoutant un Champ ImageField pour afficher chaque image de catégorie. Ajoutez simplement ImageField et définissez respectivement ses propriétés et DisplayCategoryPicture.aspx?CategoryID={0}DataImageUrlFormatString ses DataImageUrlField propriétésCategoryID. Cela crée une colonne GridView qui restitue un <img> élément dont src les références d’attribut sont {0} remplacées DisplayCategoryPicture.aspx?CategoryID={0}par la valeur de la CategoryID ligne GridView.

Ajouter un champ ImageField à GridView

Figure 12 : Ajouter un champ ImageField à GridView

Après avoir ajouté ImageField, la syntaxe déclarative de gridView doit ressembler à ce qui suit :

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

Prenez un moment pour afficher cette page via un navigateur. Notez comment chaque enregistrement inclut désormais une image pour la catégorie.

L’image de catégorie s’affiche pour chaque ligne

Figure 13 : L’image de catégorie s’affiche pour chaque ligne (cliquez pour afficher l’image de taille complète)

Résumé

Dans ce tutoriel, nous avons examiné comment présenter des données binaires. La façon dont les données sont présentées dépend du type de données. Pour les fichiers de brochure PDF, nous avons proposé à l’utilisateur un lien Afficher la brochure qui, en cliquant dessus, a dirigé l’utilisateur directement vers le fichier PDF. Pour l’image de catégorie, nous avons créé une page pour récupérer et retourner les données binaires de la base de données, puis nous avons utilisé cette page pour afficher chaque image de catégorie dans un GridView.

Maintenant que nous avons examiné comment afficher des données binaires, nous sommes prêts à examiner comment effectuer des insertions, des mises à jour et des suppressions sur la base de données avec les données binaires. Dans le tutoriel suivant, nous allons examiner comment associer un fichier chargé à son enregistrement de base de données correspondant. Dans le tutoriel après cela, nous allons voir comment mettre à jour les données binaires existantes, ainsi que comment supprimer les données binaires lorsque son enregistrement associé est supprimé.

Bonne programmation !

À propos de l’auteur

Scott Mitchell, auteur de sept livres ASP/ASP.NET et fondateur de 4GuysFromRolla.com, travaille avec les technologies Web Microsoft depuis 1998. Scott travaille en tant que consultant indépendant, formateur et écrivain. Son dernier livre est Sams Teach Yourself ASP.NET 2.0 en 24 heures. Il peut être accessible à mitchell@4GuysFromRolla.com. ou via son blog, qui peut être trouvé à http://ScottOnWriting.NET.

Merci spécial à

Cette série de tutoriels a été examinée par de nombreux réviseurs utiles. Les réviseurs principaux de ce tutoriel étaient Teresa Murphy et Dave Gardner. Vous souhaitez consulter mes prochains articles MSDN ? Si c’est le cas, déposez-moi une ligne à mitchell@4GuysFromRolla.com.