Je renvoie un ensemble de données de ma base de données MS SQL 2008R2 qui contient une table de données dont je reçois déjà des données sur ma vue Razor. J'ai ajouté un champ d'octet [] qui contient une vignette d'image que j'essaie d'afficher sur cette vue.
Comme le tableau d'octets est relativement petit, j'ai pensé que j'essaierais d'afficher le tableau d'octets en ligne. Cependant, après avoir lu il peut y avoir des problèmes liés au navigateur, j'ai abandonné cela.
La création d'une méthode de contrôleur semblait la voie à suivre, (les deux méthodes ont été trouvées ici ), mais j'ai déjà le tableau d'octets prêt à être affiché, et je n'ai pas besoin de faire un autre appel db pour obtenir il basé sur un ID.
Cela ne fonctionne pas pour des raisons évidentes:
... afficher d'autres données sur la page ....
@if (Model.dsResults.Tables[0].Rows[i]["ImageBytes"] == null)
{
<img src="@Url.Content("~/Content/Images/NoPhoto.png")" border="0" />
}
else
{
<img src="@Url.Action("GetImage", "SearchResults", new { imageBytes = Model.dsResults.Tables[0].Rows[i]["ImageBytes"] })" alt="Product Image" />
}
...
Méthode du contrôleur:
[Authorize]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetImage(byte[] imageBytes)
{
byte[] byteArray = imageBytes;
return new FileContentResult(byteArray, "image/jpeg");
}
... car cela essaie essentiellement d'envoyer le tableau d'octets sur http.
Donc, ma question est, puisque j'ai déjà le tableau d'octets sur ma vue Razor, comment puis-je l'afficher?
- Mise à jour -
Je me rends compte que le traitement dans la vue n'est pas recommandé, mais comme les données sont déjà là, ne peut-on pas faire quelque chose comme ça:
Response.Write((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]);
Ou...
Stream s = new MemoryStream(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]));
System.Drawing.Image img = new System.Drawing.Bitmap(s);
Dans d'autres articles, j'ai lu que vous faisiez une réponse.écriture (octet [] ...)) mais cela ne fonctionne pas dans ce cas.
- MISE À JOUR -
Dans ma recherche continue d'efficacité (ne pas avoir à faire une autre demande à la base de données), l'aide WebImage semble être un bon candidat. Un de ses constructeurs acceptera un tableau d'octets pour initialiser la classe, puis en utilisant la méthode .Write ("jpeg"), je peux voir l'image.
<td>
@{
WebImage webImage = new WebImage(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]));
webImage.Write("jpeg");
}
</td>
Le problème avec l'utilisation de WebImage.Write () est qu'une fois utilisée, l'image est la seule chose qui s'affiche sur la page. Existe-t-il un moyen de rendre cela directement à un "contrôle" sur une page de vue Razor?
- MISE À JOUR -
Cela continue de me déranger ... j'ai donc essayé ce qui suit, qui je pensais que cela pouvait fonctionner, car c'est ce que nous faisons à partir de l'Action ...
if (Model.dsResults.Tables[0].Rows[i]["ImageBytes"] != DBNull.Value)
{
var img1 = new FileContentResult(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]), "image/jpeg");
<text>
<img src="@new FileContentResult(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]), "image/jpeg")" />
</text>
}
... ne fonctionne pas.
Finalement, je suis allé pour la route des deux voyages. Très inefficace, car les octets d'image étaient déjà prêts à être affichés. Il devrait y avoir un contrôle d'image d'aide Web qui rendra l'image directement à partir du tableau d'octets de l'image (ou du type d'image). Peut-être qu'il y en a et je l'ai raté.
Pour obtenir les octets (oui, encore une fois):
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetThumbnailImage(string itemListID)
{
byte[] imageBytes = null;
client = new FeederServiceClient();
imageBytes = client.GetItemThumbnail( itemListID );
if (imageBytes == null)
{
return new FilePathResult("~/Content/Images/NoPhoto.png", "image/png");
}
else
{
return new FileContentResult(imageBytes, "image/jpeg");
}
}
Puis pour afficher l'image:
<img src="@Url.Content("~/Thumbnails/" + @Model.dsResults.Tables[0].Rows[i]["ItemListID"] )" />
Avec l'itinéraire suivant placé dans Global.asax:
routes.MapRoute(name: "Thumbnails", url: "Thumbnails/{itemListID}", defaults: new { controller = "Results", action = "GetThumbnailImage" });
Model.Content est une image octet [].
@{
string imageBase64 = Convert.ToBase64String(Model.Content);
string imageSrc = string.Format("data:image/gif;base64,{0}", imageBase64);
}
Utilisé comme ça:
<img src="@imageSrc" alt="@Model.Name" width="100" height="100" />
Je ne pense pas qu'avoir un tableau d'octets dans votre vue vous aidera. Vous devrez utiliser une action de contrôleur comme img src comme décrit dans votre réponse liée .
[Authorize]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Image(int id)
{
byte[] byteArray = _imageRepository.GetImage(id);
return new FileContentResult(byteArray, "image/jpeg");
}
<img src="Image/1234" alt="Image 1234"/>
Les éléments suivants fonctionneront:
<img src="data:image/jpg;base64,@(Convert.ToBase64String(item.PhotoImage))" alt="@item.orientation" />
dans mon application, j'ai défini le modèle sur la page RAZOR comme un élément plutôt que comme un modèle. PhotoImage est mon tableau d'octets (en fait un champ d'image en SQL) et Orientation n'est qu'une colonne de chaîne qui indique les métadonnées sur la photo.
J'ai cherché longtemps avant de trouver cette réponse et cela a fonctionné pour moi. J'espère que ça aide.
Vous pouvez simplement faire un Response.Write (votre tableau d'octets) et définir le Response.ContentType sur image/jpeg dans votre action Controller. Cela l'affichera directement sous forme d'image.
MISE À JOUR
Le code pourrait ressembler à ceci:
[Authorize]
[AcceptVerbs(HttpVerbs.Get)]
public void GetImage(int id)
{
byte[] imageArray = GetImageBytesFromDb(id); // some method for returning the byte-array from db.
Response.ContentType = "image/png";
Response.Write(imageArray);
}
Vous pouvez maintenant effectuer les opérations suivantes à votre avis:
<img src="@Url.Action("GetImage", "SearchResults", new { id= Model.dsResults.Tables[0].Rows[i]["Id (or whatever the id of the row is)"] })" alt="Product Image" />
En d'autres termes, au lieu d'utiliser les octets directement dans la vue, vous appelez une action de contrôleur qui retourne les octets de la base de données en fonction de l'ID de la ligne (ou du produit, si c'est l'entité de la ligne)
Ce n'est peut-être pas exactement une réponse à votre question, mais cela fonctionnera.
C'est une façon d'éviter le deuxième voyage inutile vers la base de données. memorystream to Image mais il est livré avec son propre problème lorsqu'il est utilisé dans IE9 (tous les autres navigateurs et IE semblent fonctionner correctement).
Encore plus d'informations sur le problème peuvent être trouvées ici Plus de détails sur le problème .
En fin de compte, pour ne pas avoir un hack pour ce que je pense être probablement un bug dans IE9, je suis allé avec les deux lectures, mais il ne devrait pas y avoir de besoin.
Si cela ne vous dérange pas d'utiliser Session, vous pouvez mettre votre modèle en Session (hérésie!), Puis rendre votre vue comme normale, mais maintenant où vous voulez que les images apparaissent, vous appelez l'action du contrôleur avec Url.Action en lui passant l'ID de l'image que vous voulez. Ensuite, retirez votre modèle de la session, trouvez l'image dans votre modèle pour cet identifiant, faites le FiLeContentResult (tableau, imgtype) sur votre tableau d'octets et alto - des images directement de votre modèle sur votre page. Pas besoin d'aller à nouveau dans la vraie base de données MAIS si vous utilisez Session SQL State puis obv. vous frapperez la base de données bien pire qu'avant, mais si vous êtes InProc .... eh bien, c'est une façon de le faire. Je ne sais pas si IE9 a toujours un problème mineur avec la mise en cache, mais vous pouvez toujours transmettre un identifiant unique avec votre identifiant réel pour vous assurer que cela ne se produit pas. C'est une solution minable mais ça marche.