ASP.Net MVC:モデルからバイト配列画像を表示する方法


115

ページに表示したいバイト配列イメージファイルのモデルがあります。

データベースに戻らずにどうすればよいですか?

私が目にするすべてのソリューションは、を使用ActionResultしてデータベースに戻って画像を取得していますが、モデルにはすでに画像があります...


11
「ASP.NET MVC」を単に「MVC」と呼ぶのをやめてください。1つはフレームワークで、もう1つは言語に依存しない設計パターンです。「インターネット」 -これは、IEを呼び出すようなものだ
tereško

MVC nullのときにモデルからバイト配列画像を表示する方法
Chathz 2016

回答:


214

このような何かがうまくいくかもしれません...

@{
    var base64 = Convert.ToBase64String(Model.ByteArray);
    var imgSrc = String.Format("data:image/gif;base64,{0}", base64);
}

<img src="@imgSrc" />

以下のコメントで述べたように、これはあなたの質問に答えるかもしれませんがあなたの問題を解決しないかもしれないという知識を持って上記を使用してください。あなたの問題によってはこれが解決策になるかもしれませんが、データベースへのアクセスを2回完全に排除することはしません。


6
これは、HTMLに画像を埋め込み、いくつかの標準的な画像キャッシング手法を回避することに注意してください。
Quintin Robinson

@QuintinRobinsonリクエストの数を減らします:)
dav_i

8
@dav_i 初期リクエストの数を減らします。Webパフォーマンスを最適化する場合、サーバー、中間コンテンツプラットフォーム、および情報を要求および処理するクライアントのメカニズムを理解することは非常に重要です。コメントではあまり詳細に触れたくありませんが、そのようなテクニックを使用することの意味を本当に理解する必要性を強調したいと思います。
Quintin Robinson

1
質問の答えは正しいかもしれませんが、私たちが解決しようとしている問題には欠陥があると思います。問題がデータベースへの2回の呼び出しでデータを取得し、次に秒で画像を取得することを妨げている場合は、キャッシュを実装できる種類のハンドラーを使用してサーバーの全体的な負荷を減らすのがはるかに良い解決策だと思います。Base64エンコーディングを使用して巨大なファイルをページ応答ストリームにダンプしようとしているために、アプリケーションが窒息している理由を理解しようとしているときは、より大きな全体像についてもっと考えたかったと思います。
Nick Bork 2013

2
それを再利用するためにモデルにメソッドを追加しました:public string GetBase64(){var base64 = Convert.ToBase64String(ContentImage); return String.Format( "data:image / gif; base64、{0}"、base64); }
ロドリゴロンゴ

40

これは私のために働いた

<img src="data:image;base64,@System.Convert.ToBase64String(Model.CategoryPicture.Content)" width="80" height="80"/>     

1
これも私にとってはうまくいきました、モデルからバイト配列画像をnullのときに表示する方法を教えてください
Chathz 2016

こんにちはチャッツ、ビューに移動する前に、コントローラーでモデルを検証することをお勧めします。モデルがnullの場合、デフォルトの画像を渡す
NoloMokgosi

26

画像がモデルの内部にある場合でも、これらの線に沿ったものをお勧めします。

私はあなたがビューから直接それにアクセスする直接的な方法を求めていることを理解しています、そして他の多くの人がそれに答えてそのアプローチの何が悪いのかをあなたに言ったので、これはあなたと私のために画像を非同期でロードするもう一つの方法ですより良いアプローチだと思います。

サンプルモデル:

[Bind(Exclude = "ID")]
public class Item
{
    [Key]
    [ScaffoldColumn(false)]
    public int ID { get; set; }

    public String Name { get; set; }

    public byte[] InternalImage { get; set; } //Stored as byte array in the database.
}

コントローラーのサンプルメソッド:

public async Task<ActionResult> RenderImage(int id)
{
    Item item = await db.Items.FindAsync(id);

    byte[] photoBack = item.InternalImage;

    return File(photoBack, "image/png");
}

見る

@model YourNameSpace.Models.Item

@{
    ViewBag.Title = "Details";
}

<h2>Details</h2>

<div>
<h4>Item</h4>
<hr />
<dl class="dl-horizontal">
    <img src="@Url.Action("RenderImage", new { id = Model.ID})" />
</dl>
<dl class="dl-horizontal">
    <dt>
        @Html.DisplayNameFor(model => model.Name)
    </dt>

    <dd>
        @Html.DisplayFor(model => model.Name)
    </dd>
</dl>
</div>

2
「返却ファイル(...)」とは?Fileは静的クラスではありませんか?
Ben Sewards

3
FileContentResultオブジェクト(msdn.microsoft.com/en-us/library/…)である必要があります
Louie Bacaj

13

1つの方法は、これを新しいc#クラスまたはHtmlExtensionsクラスに追加することです

public static class HtmlExtensions
{
    public static MvcHtmlString Image(this HtmlHelper html, byte[] image)
    {
        var img = String.Format("data:image/jpg;base64,{0}", Convert.ToBase64String(image));
        return new MvcHtmlString("<img src='" + img + "' />");
    }
}

次に、これを任意のビューで実行できます

@Html.Image(Model.ImgBytes)

私は本当にこれが一番好きです-モデルと.cshtmlファイルをきれいにします。すごい!!
ケン

10

バイトをbase-64エンコードできる場合は、その結果をイメージソースとして使用してみてください。モデルに次のようなものを追加します。

public string ImageSource
{
    get
    {
        string mimeType = /* Get mime type somehow (e.g. "image/png") */;
        string base64 = Convert.ToBase64String(yourImageBytes);
        return string.Format("data:{0};base64,{1}", mimeType, base64);
    }
}

そしてあなたの見解では:

<img ... src="@Model.ImageSource" />

5

画像がそれほど大きくなく、頻繁に画像を再利用する可能性があり、画像の数が多すぎず、画像が秘密ではない(つまり、画像が大きくない)場合1人のユーザーが別の人の画像を見る可能性がある場合の対処)...

ここには「if」がたくさんあるので、これは悪い考えです。

画像のバイトをCache短時間保存し、画像タグをアクションメソッドに向けることができます。アクションメソッドはキャッシュから読み取り、画像を吐き出します。これにより、ブラウザは画像を適切にキャッシュできます。

// In your original controller action
HttpContext.Cache.Add("image-" + model.Id, model.ImageBytes, null,
    Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(1),
    CacheItemPriority.Normal, null);

// In your view:
<img src="@Url.Action("GetImage", "MyControllerName", new{fooId = Model.Id})">

// In your controller:
[OutputCache(VaryByParam = "fooId", Duration = 60)]
public ActionResult GetImage(int fooId) {
    // Make sure you check for null as appropriate, re-pull from DB, etc.
    return File((byte[])HttpContext.Cache["image-" + fooId], "image/gif");
}

これには、インライン画像がIE7(または32kBより大きい場合はIE8)では機能しない古いブラウザーで機能するという追加の利点があります(または松葉杖ですか?)。


3

これは、私がプロジェクトで使用するManojの回答の修正版です。クラス、html属性を取得し、TagBuilderを使用するように更新されました。

    public static IHtmlString Image(this HtmlHelper helper, byte[] image, string imgclass, 
                                     object htmlAttributes = null)
    {
        var builder = new TagBuilder("img");
        builder.MergeAttribute("class", imgclass);
        builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));

        var imageString = image != null ? Convert.ToBase64String(image) : "";
        var img = string.Format("data:image/jpg;base64,{0}", imageString);
        builder.MergeAttribute("src", img);

        return MvcHtmlString.Create(builder.ToString(TagRenderMode.SelfClosing));
    }

これは次のように使用できます。

    @Html.Image(Model.Image, "img-cls", new { width="200", height="200" })

3

DBにbyte []が必要です。

私のbyte []は私のPersonオブジェクトにあります:

public class Person
{
    public byte[] Image { get; set; }
}


あなたはあなたのbyte []を文字列に変換する必要があります。だから、私は私のコントローラーにあります:

String img = Convert.ToBase64String(person.Image);


次に、私の.cshtmlファイルでは、モデルはViewModelです。これは私が持っているものです:

 public String Image { get; set; }


私は.cshtmlファイルで次のように使用します。

<img src="@String.Format("data:image/jpg;base64,{0}", Model.Image)" />

"data:image / image file extension ; base64、{0}、your image String "

私はそれが誰かを助けることを望みます!


1

画像を表示する場合は、ヘルパークラスまたはモデル自体にメソッドを追加し、バイト配列画像をPNGやJPGなどの画像形式に変換して、Base64文字列に変換できるようにします。それができたら、base64値をビューに次の形式でバインドします。

"data:image / [image file type extension] ; base64、[base64 string here here] "

上記はimgタグのsrc属性に割り当てられます。

これに関する唯一の問題は、base64文字列が長すぎることです。したがって、ビューに表示されている複数のモデルにはお勧めしません。


問題を提起し、ユースケースシナリオを推奨しますが、ユースケースシナリオに対する解決策はありません。それはあなたの答えをより良い/有用でより有益なものにしたでしょう。
ケン

0

以下のasnwerに基づいてヘルパーメソッドを作成しました。このヘルパーができるだけ多くのことを支援できることを非常に嬉しく思います。

モデルで:

 public class Images
 {
    [Key]
    public int ImagesId { get; set; }
    [DisplayName("Image")]
    public Byte[] Pic1 { get; set; }
  }

ヘルパーは:

public static IHtmlString GetBytes<TModel, TValue>(this HtmlHelper<TModel> helper, System.Linq.Expressions.Expression<Func<TModel, TValue>> expression, byte[] array, string Id)
    {
        TagBuilder tb = new TagBuilder("img");
        tb.MergeAttribute("id", Id);
        var base64 = Convert.ToBase64String(array);
        var imgSrc = String.Format("data:image/gif;base64,{0}", base64);
        tb.MergeAttribute("src", imgSrc);
        return MvcHtmlString.Create(tb.ToString(TagRenderMode.SelfClosing));
    }

ビューがICollectionオブジェクトを受け取っているため、ビューでforeachステートメントを使用する必要があります。

 @foreach (var item in Model)
  @Html.GetBytes(itemP1 => item.Pic1, item.Graphics, "Idtag")
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.