質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

Q&A

解決済

1回答

2800閲覧

Rezor PagesでDBの画像を表示したい

daue111

総合スコア1

.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

0グッド

0クリップ

投稿2022/04/04 03:02

編集2022/04/04 07:34

Rezor PagesでWebサービスを作ろうとしています。
Postgresqlにbytea型で入っている画像データを表示しようとしています。
チュートリアルを見ながらなんとか作ってみて、デバッグ実行してブラウザに表示してみると、画像データが「25521625521906・・・」という長い数値で表示されました。
モデルでは

c#

1 public byte[] item_image { get; set; }

というプロパティになっているので、byte配列に入った画像データをそのまま表示したからこういう表示になったんだろうと思いました。

これを画像にしたいので、base64にすればよいだろうと思い、cshtmlを書き換えてみました。
元のcshtmlがこれです。

cshtml

1@page 2@model myService.Pages.Items.DetailsModel 3 4@{ 5 ViewData["Title"] = "detail"; 6} 7 8<h1>Detail</h1> 9 10<div> 11 <hr /> 12 <dl class="row"> 13 <dt class="col-sm-2"> 14 画像連番 15 </dt> 16 <dd class="col-sm-10"> 17 @Html.DisplayFor(model => model.image_tbl.item_image_id) 18 </dd> 19 <dt class="col-sm-2"> 20 画像 21 </dt> 22 <dd class="col-sm-10"> 23 <!-- ここを書き換え --> 24 @Html.DisplayFor(model => model.v_master.item_image) 25 <!-- ここを書き換え ここまで--> 26 </dd> 27 </dl> 28</div> 29<div> 30 <a asp-page="./Index">一覧に戻る</a> 31</div>

  

  • 試行錯誤1

「ここを書き換え」の箇所を、以下のように書き換えてみました。

cshtml

1<img id="getimage" src="data: image;base64, @System.Convert.ToBase64String(model.v_master.item_image)" />

modelが存在しないというコンパイルエラーになりました。

  • 試行錯誤2

そこでこのように書き換えてみました。

cshtml

1@Html.DisplayFor(model => System.Convert.ToBase64String(model.v_master.item_image))

コンパイルエラーは出ませんでしたが、デバッグ実行してみると、以下のようなエラーになりました。
An unhandled exception occurred while processing the request.
InvalidOperationException: Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.
@Html.DisplayForに続けて関数を書くことはできないらしいと分かりました。

  • 試行錯誤3

ではモデルの方で書き換えてしまえばよいのではとこのように書き換えてみました。

c#

1public byte[] _item_image; 2public byte[] item_image 3{ 4 get 5 { 6 string image64 = "data:image/jpeg;base64," + Convert.ToBase64String(_item_image); 7 return image64; 8 } 9 set { _item_image = value; } 10}

byte[]とstringの型違いでコンパイルエラーになりました。

  • 試行錯誤4

ではメソッドを追加してしまえばいいのではと、モデルの方に関数を追加してみました。

c#

1public byte[] _item_image; 2public byte[] item_image 3{ 4 get { return _item_image; } 5 set { _item_image = value; } 6} 7public string GetItemImage() 8{ 9 return "data:image/jpeg;base64," + Convert.ToBase64String(_item_image); 10}

cshtmlでは関数の方を書いてみました。

cshtml

1@Html.DisplayFor(model => model.v_master.GetItemImage())

これもコンパイルエラーにはなりませんでしたが、デバッグ実行すると、さっきも見たエラーになりました。
An unhandled exception occurred while processing the request.
InvalidOperationException: Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.

ここでお手上げになってしまいました。画像で表示するにはどうすればいいのでしょうか。


開発環境は以下の通りです :
・OS Windows10-64bit
・Visual Studio のバージョン 2019
・.NET Framework なのか Core のどっちかなのかとそのバージョン
プロジェクトのプロパティの「対象のフレームワーク」に「.NET core3.1」とあるのでこれだと思います。
・Visual Studio でプロジェクトを作る時に使ったテンプレートは何か
ロジェクトを作るときのウィザードの「新しいプロジェクトの作成」で、「ASP.NET Core Webアプリ サンプルのASP.NET Razor PagesコンテンツでASP.NET Coreアプリケーションを作成するためのプロジェクト テンプレートです」というのを選択しました。テンプレートとはこれのことでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/04/04 04:22 編集

ASP.NETの話なら ASP.NET のタグをつけてください。 そして、開発環境(OS は何か, Visual Studio のバージョン、.NET Framework なのか Core のどっちかなのかとそのバージョン、Visual Studio でプロジェクトを作る時に使ったテンプレートは何かなど)を書いてください。
daue111

2022/04/04 06:29

ASP.NETとは何のことか調べました。それのことです。タグ付けました。有難う御座います。 開発環境について何を書けばいいか教えていただいて有難う御座います。 以下の通りです。 ・OS Windows10-64bit ・Visual Studio のバージョン 2019 ・.NET Framework なのか Core のどっちかなのかとそのバージョン   プロジェクトのプロパティの「対象のフレームワーク」に「.NET core3.1」とあるのでこれだと思います。 ・Visual Studio でプロジェクトを作る時に使ったテンプレートは何か   ロジェクトを作るときのウィザードの「新しいプロジェクトの作成」で、「ASP.NET Core Webアプリ サンプルのASP.NET Razor PagesコンテンツでASP.NET Coreアプリケーションを作成するためのプロジェクト テンプレートです」というのを選択しました。テンプレートとはこれのことでしょうか?
退会済みユーザー

退会済みユーザー

2022/04/04 07:27

追加情報は上の質問欄を編集してそちらに追記してください。ここコメント欄は「質問への追記・修正の依頼」を行う場所ですので。
退会済みユーザー

退会済みユーザー

2022/04/04 13:54

質問者さん、その後無言ですが、解決したならクローズする、不明な点があれば質問するなどのフォローをお願いします。
guest

回答1

0

ベストアンサー

質問のコメントに返事がないのでいろいろ不明ですが、とりあえず参考になりそうな記事を紹介しておきます。

画像をアップロードして SQL Server に保存 (CORE)
http://surferonwww.info/BlogEngine/post/2021/11/24/upload-image-file-and-save-it-to-sql-server-in-aspnet-core-mvc.aspx

DB からファイルを取得してきて、そのバイト列をダウンロードする API を作って(上の記事では Controller の GetThumb メソッド)、その URL をhtml の img 要素の src 属性に設定する(上の記事では Index.cshtml 参照)ことで表示できます。


【追記】

下のコメント欄の私のコメントで「後で Razor Pages 用のサンプルを回答欄に追記しておきます」と書いた件です。

紹介した記事のプロジェクト(Razor Pages も使えるように設定してある)のルート直下に Pages フォルダを追加し、それに FetchThumbImage という名前の Razor ページを追加し、紹介した記事の GetThumb メソッドを移植したのが下記のコードです。

#nullable disable using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using MvcCore6App.Data; using MvcCore6App.Models; using Microsoft.EntityFrameworkCore; namespace MvcCore6App.Pages { public class FetchThumbImageModel : PageModel { private readonly FileContext _context; public FetchThumbImageModel(FileContext context) { _context = context; } public async Task<IActionResult> OnGetAsync(int? id) { if (id == null) { return NotFound(); } FileEntity file = await _context.Files .FirstOrDefaultAsync(m => m.Id == id); if (file == null) { return NotFound(); } return File(file.ThumbImage, "image/jpeg"); } } }

上記を使って画像を表示するには、例えば、以下のように img 要素の src 属性に上の URL とクエリ文字列を設定すれば、

イメージ説明

以下の通り画像は表示されます。お試しください。

イメージ説明


【追記2】

ファイルのダウンロードについては以下の記事が参考になると思いますので、興味があれば読んでください。

ASP.NET Core MVC でファイルダウンロード
http://surferonwww.info/BlogEngine/post/2020/01/20/aspnet-core-mvc-file-download.aspx

上記は MVC の記事ですが、記事に書いてある "FileResult Class を継承する VirtualFileResult, FileContentResult, FileStreamResult, PhysicalFileResult オブジェクトのいずれかを Controller のアクションメソッドで生成して返してやることになります" の「Controller のアクションメソッド」を、Razor ページでは「.html.cs の OnGet メソッド」に読み替えてやれば Razor Pages でも書いてあることは有効です。

なお、上の記事の File メソッドの設定は、通知バーを表示するため File メソッドの第 3 引数にファイル名を設定して応答ヘッダに Content-Disposition が含まれるようにしていますが、今回の話のように img 要素に画像を表示するの場合は Content-Disposition は不要(というより、通知バーが表示され望む動きにならない)です。

上の【追記】コードでは第 2 引数までしか設定していないのはそれが理由です。

投稿2022/04/04 05:04

編集2022/04/05 02:42
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

daue111

2022/04/04 06:47

情報有難う御座います。 私のソースにはなぜかControllerがないのですが(使っている「テンプレート」が違うから?)、PageModelというのがその代わりになるものかもしれません。その方向で調べてみます。
退会済みユーザー

退会済みユーザー

2022/04/04 07:35

紹介した記事は MVC なので Controller を使います。Razor Pages では Controller は使いませんが、同様なダウンロードの機能は作成できるはずです。razor pages file download などをキーワードにググってみると参考になる記事が見つかると思います。
退会済みユーザー

退会済みユーザー

2022/04/04 13:54

質問者さん、その後無言ですが、解決したならクローズする、不明な点があれば質問するなどのフォローをお願いします。
daue111

2022/04/05 01:14

すいませんまだ調査継続中です。 cshtml.cs(PageModel)に、教えていただいたサイトのControllerにあった ```c# public async Task<IActionResult> GetThumb(int? id) ``` を書いて、cshtmlで ```cshtml @{ <img src="./GetThumb?id=1" /> } ``` と書いたら呼び出せるのではと思ったのですが、ブレークポイントを置いてデバッグ実行しても止まらず、パスが違うのか書き方が違うのか試行錯誤しているところです。
daue111

2022/04/05 01:37

あ、だからdownloadで検索なのか! ダウンロード処理を呼ぶサンプルの、ダウンロード処理の中身を、画像表示処理に書き換えればいいという話ですね!
退会済みユーザー

退会済みユーザー

2022/04/05 01:49

質問者さんが使った「ASP.NET Core Web アプリ」のテンプレートで作った Razor Pages アプリでは MVC が使えるようになってないので、紹介した記事の GetThumb メソッドと同じように書いたのではダメかと思います。後で Razor Pages 用のサンプルを回答欄に追記しておきます。
daue111

2022/04/05 02:46

有難う御座います。 えーと、まず紹介いただいたサイトにはslnとかのファイルがないので、それらを作るためにMVCを使うテンプレートを探してそれで新しいソリューションを作り、そこにサイトのソースを当てはめて、SQL ServerをPostgreSQLに置き換えて、追記いただいた追加を加えてやれば画像が表示できるということですね。やってみます。
退会済みユーザー

退会済みユーザー

2022/04/05 03:09

違います。質問者さんが「ASP.NET Core Web アプリ」のテンプレートで作った Razor Pages アプリのプロジェクトのルート直下に Pages というフォルダがあるはずなので、その中に上の【追記】で紹介したような Razor ページを追加すれば済むはずです。(もちろん【追記】のコードをそのままコピペしてはダメですよ。コンテキストクラスとかバイト列を取得するコードは質問者さん独自のものに書き換えないと)
daue111

2022/04/05 03:09

ところで、ダウンロード処理を呼ぶサンプルのダウンロード処理の中身を画像表示処理に書き換える方向で調査中に、 https://qiita.com/kenjiuno/items/26ee80b13fc70484664b を見つけて、それをもとに cshtmlに以下を追加 @{ <a asp-page="./" asp-page-handler="Download">Excel</a> } cshtml.csに以下を追加 public IActionResult OnGetDownloadAsync() { //ここにブレークポイントを置いて呼び出されるか確認 return NotFound(); } してみましたが、なぜか元々あったこのページを表示する public async Task<IActionResult> OnGetAsync(int? id) の方が呼ばれました。 やっぱり追加していただいた方で試してみます。
退会済みユーザー

退会済みユーザー

2022/04/05 03:22

それはその記事を書いた人に聞いてはいかがですか? 記事を見ると "Problems.cshtml の方にダウンロードのリンクを設置します" とか書いてあるけど Problems.cshtml って何???・・・という感じ。さらにあなたがその記事を参考に何をしたのかも不明。私が関与できる範囲を超えてます。なので私に聞かないでください。
daue111

2022/04/05 05:12

有難う御座います。 自分のプロジェクトに入れてみます。
退会済みユーザー

退会済みユーザー

2022/04/05 05:44 編集

> 自分のプロジェクトに入れてみます。 何を入れるのでしょう? Razor のサンプルコードまで書いたので、それを見ればすぐ解決できると思っていたのですが、迷走していませんか? 何をどこにどう入れるのか詳しく書いてもらえると役に立つかもしれないコメントが出せるかもしれないのに、それだけのレスでは何ともできません
daue111

2022/04/05 06:46 編集

> 何を入れるのでしょう? 「追記」で書いていただいたPazorページ(自分の環境に合わせてクラス名などを変えた)を、自分のRazor Pages アプリの Pagesフォルダに入れました。 途中で、すでにあるPazorページを「追記」で書いていただいたように書き換えれば良いと気づき、そのようにしました。 結果、下記のようにソースに書き足すことで、画像が表示されました! 1個は。 Index.cshtml : <img src="./FetchThumbImage?id=1" alt="" /> FetchThumbImage.cshtml.cs : public async Task<IActionResult> OnGetAsync(int? id) {   file_model = await _context.file_model.FirstOrDefaultAsync(m => m.Id== id);   return File(file_model.image1, "image/jpeg"); } テーブルには2個画像があるので、もう1個も表示したいと思いました。 方法を考えました。 ・案1 OnGetAsyncの戻り値で画像を二個返す →やり方が想像つかない。 ・案2 OnGetAsyncを二個書く →OnGetAsyncは定義済みというエラーになる。没。 ・案3 OnGetAsyncの引数に、どちらの画像を表示するのか識別するフラグを追加する →以下のように書き換えてみました。 Index.cshtml : <img src="./FetchThumbImage?flg=1&id=1" alt="" /> <img src="./FetchThumbImage?flg=2&id=1" alt="" /> FetchThumbImage.cshtml.cs : public async Task<IActionResult> OnGetAsync(int? flg, int? id) {   file_model = await _context.file_model.FirstOrDefaultAsync(m => m.item_id == id);   if(flg == 1)     return File(file_model.image1, "image/jpeg");   else if(flg == 2)     return File(file_model.image2, "image/jpeg"); } しかし、画像は2個とも表示されません。 OnGetAsyncの中にブレークポイントを置いてもブレークしないので、処理が呼ばれていないようです。 こういう書き方は駄目なんでしょうか。
退会済みユーザー

退会済みユーザー

2022/04/05 07:12 編集

> テーブルには2個画像があるので、もう1個も表示したいと思いました。 画像データのある DB のテーブルの構造が不明ですが、一番最初の回答で紹介した記事の「(4) SQL Server データベース作成」にある画像と似たようになっているから質問者さんのケースでも、 > file_model = await _context.file_model.FirstOrDefaultAsync(m => m.Id== id); というコードで id を指定して当該 id のレコードを取得できるのだろうと想像してますが、違うのですか? だから、上に書いてあるように、 > 結果、下記のようにソースに書き足すことで、画像が表示されました! 1個は。 > Index.cshtml : > <img src="./FetchThumbImage?id=1" alt="" /> > > FetchThumbImage.cshtml.cs : > public async Task<IActionResult> OnGetAsync(int? id) > { >   file_model = await _context.file_model.FirstOrDefaultAsync(m => m.Id== id); >   return File(file_model.image1, "image/jpeg"); > } ということで期待通りの結果になったのでは? であれば、FetchThumbImage.cshtml.cs の方をいじる必要はなくて、単に以下のように img 要素を必要な数だけ増やせばよいはずですけど? <img src="./FetchThumbImage?id=1" alt="" /> <img src="./FetchThumbImage?id=2" alt="" /> ブラウザは上のコードを受けると、まず ./FetchThumbImage?id=1 に要求を出して当該画像データをサーバーから取得して表示し、次に ./FetchThumbImage?id=2 に要求を出して・・・という動きをします。
daue111

2022/04/05 07:19 編集

レコードが別々ならidを変えればいいのですが、一つのレコードにimage1カラムとimage2カラムがあるので、どっちもidは1なのです。 表示されました! 原因は、FetchThumbImage.cshtml.csに   public async Task<IActionResult> OnGetAsync(int? id) が残っていたためでした。 これをコメントアウトしたところ、   public async Task<IActionResult> OnGetAsync(int? flg, int? id) が呼ばれました。 やりたかったことができるようになりました。 有難う御座いました。 本題の話だけでなく質問の仕方も教えていただいて本当に助かりました。
退会済みユーザー

退会済みユーザー

2022/04/05 07:58

> 一つのレコードにimage1カラムとimage2カラムがあるので、どっちもidは1なのです。 一つのレコードは 1 回 SELECT クエリを投げれば取得できますが、質問者さんにのやり方では 2 回 SELECT クエリ投げることになりませんか? であれば、次の課題としてその無駄を何とかすることを考えるのが良さそうです。
daue111

2022/04/05 08:39 編集

> 2 回 SELECT クエリ投げることになりませんか? そうなんですね。DBContextはMFCでいうDataGridのようなもので取ってきたデータをキャッシュしてくれるのだろうと勝手に想像してました。 どうすればいいんだろう。 こういう変更でしょうか? 現状 : ・OnGetAsyncを二回呼ぶ ・戻り値は以下の要領で画像一個返す   return File(file_model.image1, "image/jpeg"); 変更後 : ・OnGetAsyncは一回だけよぶ ・戻り値で画像を二個返す。多分   return Page(); って書く? でもどうやったらそのPageに画像が2個入る? (すいません明日は別件作業で一日ソースを触れないです)
退会済みユーザー

退会済みユーザー

2022/04/05 09:07

その件は別途よく考えてから必要があれば別に新たにスレッドを立てて質問してください。
退会済みユーザー

退会済みユーザー

2022/04/06 02:53

> データをキャッシュしてくれるのだろうと勝手に想像してました。 Web アプリはステートレスです。FetchThumbImage が呼ばれて、サーバーが応答を返した後はサーバーではメモリは消去されて何も残ってません。 キャッシュするためには自分でそのためのコードを書くことになります。 今頃気が付いてなんですが、質問欄の「試行錯誤1」で Data URL 形式にすることを考えておられたんですね。それがクエリを何度も投げるのを避けるには有効な手段だと思います。エラーになったのは書き方の問題です。 Data URL を使った場合は、BASE64 エンコードによりサイズが増えること、ブラウザはその画像をキャッシュできないというデメリットがありますが、それとクエリが複数回投げられるデメリットを天秤にかけて考えるという話になると思います。
daue111

2022/04/07 04:14

ヒント有難う御座います。調べてみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問