ASP.NET Core

【ASP.NET Core】C# 画像ファイルをBLOBでDBに登録する方法

画像ファイルをDBに保存する方法として、varbinary(MAX)のカラムにバイナリデータを登録するやり方があります。本記事ではASP.NET Core + Dapper で登録する方法を紹介します。

【検証環境】Visual Studio 2019 / ASP.NET Core 3.1 / SQL Server 2019

DBに画像を保存する方法

DBに画像を保存する方法は大きく分けて2通りあります。

ファイルパスを保存

画像はDBの外に保存し、ファイルパスをデータベースに格納するやり方です。
ファイルパスを保存するだけなので、DBの容量を節約できます。

BLOB(バイナリデータ)を保存

varbinary(MAX)のカラムにバイナリデータを格納するやり方です。
レコードの容量が大きくなってしまいますが、メリットも多くあります。

それぞれの詳しいメリット・デメリットはこちらのサイトを参照してください。

サンプルコード

先にテーブルを準備します。
テーブル「Images」に カラムvarbinary(MAX)・NULL許容「Image」を作成します。


PostController と Post\Index.cshtml を作成します。
Dapperの使い方はこちらを参照して下さい。

<form method="post" enctype="multipart/form-data" asp-controller="Post" asp-action="Index">
    <div class="form-file">
        @*画像アップロード用*@
        <input type="file" class="form-file-input" id="image" name="formFile" />
    </div>
    <div>
        @*登録ボタン*@
        <input type="submit" value="登録" name="btnname"> 
    </div>
    <div>
        @*画像取得ボタン*@
        <input type="submit" value="画像取得" name="btnname">
        @*画像表示用*@
        <img id="getimage" style="width: 100px;" src="data: image;base64, 
             @System.Convert.ToBase64String(ViewBag.image ?? new byte[] { })" />
    </div>
    <div>
        @*メッセージ*@
        @ViewBag.message
    </div>
</form>


IFormFile で画像を受け取って、MemoryStreamにコピーして、ToArrayでbyte配列に変換すれば登録できる形式になります。

using Dapper;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Data.SqlClient;
using System.IO;

public class PostController : Controller
{
    public ActionResult Index()
    {
        return View();
    }


    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Index(IFormFile formFile, string btnname)
    {
        try
        {
            ViewBag.message = "";

            if (btnname == "登録")
            {
                InsertImage(formFile, btnname);
                ViewBag.message = "登録完了";
            }
            else if(btnname == "画像取得")
            {
                GetImage();
            }
            return View();
        }
        catch(Exception ex)
        {
            ViewBag.message = ex.Message;
            return View();
        }
    }

    private void InsertImage(IFormFile formFile, string value)
    {
        var connectionString = "環境に合わせてください。";
        using (var connection = new SqlConnection(connectionString))
        {
            //接続
            connection.Open();
            using (var tx = connection.BeginTransaction())
            {
                try
                {
                    //レコード削除
                    var sqlDelete = "DELETE FROM Images";

					//トランザクションを使う場合、第2引数にオブジェクトを渡さないとエラーになる(空でもOK)
                    connection.Execute(sqlDelete, new { } ,tx);

                    //データ挿入
                    var sqlInsert = "INSERT INTO Images (Image) VALUES (@Image)";
                    var ms = new MemoryStream();
                    formFile.CopyTo(ms);
                    var param = new { Image = ms.ToArray() };
                    connection.Execute(sqlInsert, param, tx);

                    //コミット
                    tx.Commit();
                }
                catch (Exception)
                {
                    //ロールバック
                    tx.Rollback();
                    throw;
                }
            }
        }
    }
    private void GetImage()
    {
        var connectionString = "環境に合わせてください。";
        using (var connection = new SqlConnection(connectionString))
        {
            //接続
            connection.Open();
            try
            {
                //レコード1件取得
                var sql = "SELECT TOP(1) Image FROM Images";
                var image = connection.QueryFirst<byte[]>(sql);
                ViewBag.image = image;
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}


アプリを起動して、URLに「/Post」を入力して遷移させます。
すると最初にこのような画面が表示されます。


画像ファイルを選択して、登録ボタンを押下すると、「登録完了」のメッセージが表示されます。

画像取得ボタンを押下すると、登録された画像が表示されることが確認できます。


DBからもバイナリデータが格納されていることが確認できます。

エンジニアの転職ならこれ!

【第二新卒向け】マイナビジョブ20's

マイナビジョブ20'sは、20代・第二新卒・既卒向けの転職エージェントです。

▼こんな方におすすめ
・はじめて転職しようと思っている
・転職できるだけのスキルが自分にあるか不安
・手厚いサポートを受けたい

【フリーランス向け】安心保障と豊富な案件紹介 Midworks

Midworksは豊富な案件と「フリーランス」と「正社員」の良いとこ取りをした働き方を実現する手厚い保障が特徴です。

▼こんな方におすすめ
・現在正社員でフリーランスになろうか悩んでいる
・フリーランスとして働いているが、先行きが不安がある  (安定的な案件確保や保障など)
・自分の市場価値を知りたい、見合った案件で参画したい
・今後のキャリアビジョンを踏まえて案件を選びたい

【未経験向け】自宅で現役エンジニアから学べる TechAcademy

テックアカデミーは、現役エンジニアから学べるオンラインに特化したプログラミングスクールです。
講師は全員、通過率10%の選考に合格した現役エンジニア。
確かなスキルをもとに受講生をマンツーマンサポートします。


▼こんな方におすすめ
・自宅にいながらオンライン完結で勉強できる
・受講生に1人ずつ現役エンジニアのパーソナルメンターが専属でつく
・チャットで質問すればすぐに回答が返ってくる
・オリジナルサービスやオリジナルアプリなどの開発までサポート