13
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

c# テキストエリア上でペーストした画像をSQL Serverに保存する

Last updated at Posted at 2015-09-23

#概要
HTMLのテキストエリア上でクリップボード上の画像データをペーストすると、jQuery AJAXでPOSTして、ASP.NET MVCからSQL Serverに保存します。その後、SQL Serverの画像データを取り出しHTMLに表示するまでの一連の処理の実装について記載します。

#実現イメージ
テキストエリアに画像をペーストすると、画像が画面に表示されます。Qiitaの編集画面の機能でアイディアを得てASP.NETに実装してみました。
image

#コード例
##SQL Serverの準備
画像をimage型として保存するテーブルをSQL Serverに作成します。DB名はTestDBとしました。

Create.sql
CREATE DATABASE [TestDB]
GO
USE [TestDB];
CREATE TABLE [dbo].[Images](
	[Id] [bigint] IDENTITY(1,1) NOT NULL,
	[Bin] [image] NOT NULL,
CONSTRAINT [PK_Images] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

##HTML
jQuery及び後述のtest.jsを読み込んだHTMLです。テキストエリアと格納済のイメージを表示するDIVを配置しました。

sample.html
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <script src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.4.min.js"></script>
    <script src="Scripts/test.js"></script>
    <title></title>
	<meta charset="utf-8" />
</head>
<body>
    <textarea id="Images_Bin" class="upload-image" rows="5" placeholder="ここに画像をペースト"></textarea>
    <div id="results" style="margin-top:10px;"></div>
</body>
</html>

##JavaScript(jQuery)
テキストエリア.upload-imageのペーストイベントをフックしてAJAX通信で画像データをペーストします。その後、サーバから返却される画像のIdを表示するimgタグを動的に生成します。

test.js
$(document).on('paste', '.upload-image', function (e) {
    var items = e.originalEvent.clipboardData.items;
    for (var i = 0 ; i < items.length ; i++) {
        var item = items[i];
        if (item.type.indexOf("image") != -1) {
            var data = new FormData();
            data.append('Images_Bin', item.getAsFile());
            requestFile('/images/create', 'post', data);
        }
    }
});

function requestFile(requestUrl, methodType, data) {
    return $.ajax({
        url: requestUrl,
        type: methodType,
        cache: false,
        contentType: false,
        processData: false,
        data: data,
        success: function (o) {
            $('#results').prepend('<img src="/images/show/' + o + '">');
            return true;
        },
        error: function (xhr, status, err) {
            return false;
        }
    });
};

##ASP.NET MVC コントローラー
Createメソッドは、クライアントから送信された画像データをSQL Serverに挿入します。ShowメソッドはSQL Serverから取り出した画像データ(byte配列)をFileContentResultに変換してクライアントに送信します。

ImagesController.cs
using System.Web.Mvc;
using WebApplication1.Models;
namespace WebApplication1.Controllers
{
    [AllowAnonymous]
    public class ImagesController : Controller
    {
        [HttpGet]
        public ActionResult Show(long id)
        {
            var image = new ImageModel(id).Show();
            return new FileContentResult(image, "image/jpeg");
        }

        [HttpPost]
        public string Create()
        {
            var id = new ImageModel().Create();
            return id.ToString();
        }
    }
}

##ASP.NET MVCモデル
CreateメソッドはRequest.Filesに格納されている画像データをbyte配列に変換し、SQL ServerにInsertします。ShowメソッドはSQL Serverの画像データを呼び出し元のコントローラーに返却します。

ImageModel.cs
using System.Data;
using System.Data.SqlClient;
using System.Web;
namespace WebApplication1.Models
{
    public class ImageModel
    {
        const string ConnectionString = "Server=tcp:(local),1433;Database=TestDB;Integrated Security=SSPI;";
        public long Id;

        public ImageModel()
        {
        }

        public ImageModel(long id)
        {
            Id = id;
        }

        public byte[] Show()
        {
            var dt = new DataTable();
            var conn = new SqlConnection(ConnectionString);
            var cmd = new SqlCommand("select [Images].[Bin] from [Images] where [Images].[id]=@Id;", conn);
            cmd.Parameters.AddWithValue("@Id", Id);
            var adp = new SqlDataAdapter(cmd);
            adp.Fill(dt);
            return dt.Rows[0][0] as byte[];
        }

        public long Create()
        {
            var conn = new SqlConnection(ConnectionString);
            var cmd = new SqlCommand("insert into [Images]([Images].[Bin]) values(@Bin); select @@identity;", conn);
            cmd.Parameters.AddWithValue("@Bin", File("Images_Bin"));
            conn.Open();
            long.TryParse(cmd.ExecuteScalar().ToString(), out Id);
            conn.Close();
            return Id;
        }

        public static byte[] File(string key)
        {
            var file = HttpContext.Current.Request.Files[key];
            var bin = new byte[file.ContentLength];
            file.InputStream.Read(bin, 0, file.ContentLength);
            return bin;
        }
    }
}

#動作確認環境
・Windows 10
・IIS
・.NET Framework4.6
・C# 6.0
・jQuery 2.1.4
・Google Chrome / Microsoft Edge
※ IEの場合、クリップボードに画像が入っているとペースト処理が実行できませんでした。(右クリックで貼り付けもグレーアウト)

#実装のポイント
##ファイルとして送信するためにjQuery Ajaxで指定する

contentType: false,
processData: false,

##ファイルとして送信するためにjQuery Ajaxで指定しない

// dataType: 'json',

##ASP.NET MVCでRequest.Filesから画像を受け取り、バイト配列に変換してDBに格納

var file = HttpContext.Current.Request.Files[key];
var bin = new byte[file.ContentLength];
file.InputStream.Read(bin, 0, file.ContentLength);
return bin;

##ASP.NET MVCで画像を出力する際はFileContentResultに変換

return new FileContentResult(image, "image/jpeg");

#その他
上記のコードは最小限の記述しかしていないため、エラー処理等は別途考慮が必要です。

#参考にしたサイト
・クリップボードの画像ファイルをアップロードする
http://qiita.com/volpe28v@github/items/dc100c75c2371bb82a3b
・Upload files in ASP.NET MVC with JavaScript and C#.
https://cmatskas.com/upload-files-in-asp-net-mvc-with-javascript-and-c/

13
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?