#概要
HTMLのテキストエリア上でクリップボード上の画像データをペーストすると、jQuery AJAXでPOSTして、ASP.NET MVCからSQL Serverに保存します。その後、SQL Serverの画像データを取り出しHTMLに表示するまでの一連の処理の実装について記載します。
#実現イメージ
テキストエリアに画像をペーストすると、画像が画面に表示されます。Qiitaの編集画面の機能でアイディアを得てASP.NETに実装してみました。
#コード例
##SQL Serverの準備
画像をimage型として保存するテーブルをSQL Serverに作成します。DB名はTestDBとしました。
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を配置しました。
<!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タグを動的に生成します。
$(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に変換してクライアントに送信します。
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の画像データを呼び出し元のコントローラーに返却します。
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/