Affichage de données binaires dans les contrôles web de données (C#)
par Scott Mitchell
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 desBrochurePath
valeurs
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
.
Figure 1 : Entrer manuellement les valeurs de la colonne de table Categories
BrochurePath
(cliquez pour afficher l’image de taille complète)
Étape 2 : Fournir un lien de téléchargement pour les brochures dans un GridView
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()
.
Figure 2 : Créer un ObjetDataSource nommé CategoriesDataSource
(cliquez pour afficher l’image de taille complète)
Figure 3 : Configurer ObjectDataSource pour utiliser la classe (Cliquez pour afficher l’image CategoriesBLL
de taille complète)
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
, Description
NumberOfProducts
et 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.
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é BrochurePath
sur .
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.
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)
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 NULL
le 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.
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 ».
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
.
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.
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.
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.