web-dev-qa-db-ja.com

Razor / MVC3でデータベース画像(bytes [])を表示しますか?

Razorビューで既にデータを取得しているデータテーブルを含むMS SQL 2008R2データベースからデータセットを返しています。そのビューに表示しようとしている画像のサムネイルを含むbyte []フィールドを追加しました。

バイト配列は比較的小さいので、バイト配列をインラインで表示してみようと思いました。しかし、読んだ後、ブラウザ関連の問題があるかもしれないので、私はこれを断念しました。

コントローラメソッドの作成は進むべき道のように見えました(両方のメソッドが見つかりました here )が、私はすでにビューに進む準備ができているバイト配列を持っているので、取得するために別のdb呼び出しを行う必要はありませんIDに基づいています。

これを行うことは、明らかな理由で機能しません:

...ページに他のデータを表示しています....

@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" />
}

...

コントローラー方式:

[Authorize]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetImage(byte[] imageBytes)
{
    byte[] byteArray = imageBytes;
    return new FileContentResult(byteArray, "image/jpeg");
}

...これは本質的にバイト配列をhttp経由で送信しようとしているためです。

だから、私の質問は、Razorビューにすでにバイト配列があるため、どのように表示するのですか?

-更新-

ビューでの処理はお勧めしませんが、データはすでにそこにあるため、次のようなことはできません。

Response.Write((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]);

または...

Stream s = new MemoryStream(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]));
System.Drawing.Image img = new System.Drawing.Bitmap(s);

他の投稿では、Response.Write(byte [] ...))を実行することを読みましたが、この場合は機能しません。

-UPADATE-

効率を追求している私の継続的な調査(データベースに別の要求をする必要がない)では、 WebImage ヘルパーが良い候補のようです。そのコンストラクターの1つは、バイト配列を受け入れてクラスを初期化し、次に.Write( "jpeg")メソッドを使用して、画像を表示できます。

<td>
    @{
        WebImage webImage = new WebImage(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]));
        webImage.Write("jpeg");
    }
</td>

WebImage.Write()を使用する際の問題は、一度使用すると、画像がページにレンダリングされる唯一のものになることです。これをRazorビューページの「コントロール」に直接レンダリングする方法はありますか?

-更新-

これは私を悩ませ続けます...それで、私は次のことを試しました、これは私たちがアクションからやっていることなので、私はうまくいくと思っています.

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

...機能しません。

22
ElHaix

結局、私は2つの旅行ルートに行きました。画像バイトがすでにビューに表示される準備ができているため、非常に非効率的です。画像のバイト配列(または画像タイプ)から直接画像をレンダリングするWebヘルパー画像コントロールが必要です。多分そこにあり、私はそれを逃した。

バイトを取得するには(はい、繰り返します):

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

次に、画像を表示します。

<img src="@Url.Content("~/Thumbnails/" + @Model.dsResults.Tables[0].Rows[i]["ItemListID"] )" />

次のルートがGlobal.asaxに配置された場合:

routes.MapRoute(name: "Thumbnails", url: "Thumbnails/{itemListID}", defaults: new { controller = "Results", action = "GetThumbnailImage" });
9
ElHaix

Model.Contentはbyte []画像です。

@{
    string imageBase64 = Convert.ToBase64String(Model.Content);
    string imageSrc = string.Format("data:image/gif;base64,{0}", imageBase64);
}

このように使用されます:

<img src="@imageSrc" alt="@Model.Name" width="100" height="100" />
20
lbancarz

私はあなたのビューにバイト配列があることはあなたを助けるとは思わない。 リンクされた回答 で説明されているように、コントローラーアクションをimg srcとして使用する必要があります。

[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"/>
5
jrummell

以下が機能します:

<img src="data:image/jpg;base64,@(Convert.ToBase64String(item.PhotoImage))" alt="@item.orientation" />

私のアプリケーションでは、RAZORページでモデルをモデルではなくアイテムとして定義しました。 PhotoImageは私のバイト配列(実際はSQLの画像フィールド)で、Orientationは写真に関するメタデータを伝える文字列列です。

私はこの答えを見つける前に長い間検索しましたが、うまくいきました。それが役に立てば幸い。

3
ron icard

Response.Write(バイト配列)を実行し、コントローラーアクションでResponse.ContentTypeをimage/jpegに設定するだけです。それはそれをイメージとして直接表示します。

[〜#〜]更新[〜#〜]

コードは次のようになります。

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

これで、ビューで次のことができるようになります。

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

したがって、言い換えると、ビューでバイトを直接使用する代わりに、行のID(または行のエンティティの場合は積)に基づいてデータベース行からバイトを返すコントローラーアクションを呼び出します。

それはあなたの質問に対する正確な答えではないかもしれませんが、それはうまくいきます。

2
Yngve B-Nilsen

これは、2回目の不要なデータベースへのアクセスを回避する1つの方法です。 Imageへのメモリストリーム ですが、IE9で使用すると、それ自体に問題があります(他のすべてのブラウザおよびIEバージョンは正常に動作するようです)。

問題に関するさらに詳しい情報は、こちら その他の問題の詳細 で確認できます。

結局、おそらくIE9のバグだと思うことにハックしないために、「2回」の読み取りを行いましたが、必要はありません。

0
K. Bob

セッションを使用しても構わない場合は、モデルをセッション(異端!)に配置し、ビューを通常どおりレンダリングしますが、ここで画像を表示する場所に、Url.ActionがIDを渡すコントローラーアクションを呼び出します。あなたが欲しい画像。次に、モデルをセッションから戻し、モデル内でそのIDの画像を見つけ、バイト配列とviolaでFiLeContentResult(array、imgtype)を実行します。モデルからページに直接画像が送られます。実際のデータベースに再度アクセスする必要はありませんが、Session SQL Stateを使用すると、obvになります。あなたは以前よりもはるかに悪いデータベースにヒットしますが、あなたがInProcである場合...まあそれはそれを行う1つの方法です。 IE9にまだキャッシュに関する小さな問題があるかどうかはわかりませんが、実際のIDと共に一意のIDを常に渡して、それが起こらないようにすることができます。これは粗末な解決策ですが、機能します。

0
K. Bob