WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

Employees の Photo

by WebSurfer 4. June 2021 14:51

Microsoft のサンプル SQL Server データベース Northwind の Employees テーブルの Photo フィールドの画像データを取得して表示する方法を書きます。

Employees の Photo

アプリから Photo フィールドのバイト列データを取得するのは ADO.NET + SqlClient を使って可能です。問題はそのバイト列を加工して jpg とか png 形式にすることで、それをどうしたらよいかという話です。

Photo フィールドの画像データは Bitmap 形式のバイト列なのですが、ネットの記事 Displaying images in SAPUI5 received from the Northwind OData service によると "The 78 superfluous bytes are a proprietary OLE header that Access creates when saving bitmaps." という余計なものが付いています。(Microsoft のドキュメントもそのような情報があったのですが行方不明)

実際、Photo フィールドのバイト列を取得してそれをそのまま stream に変換し、new Bitmap(stream) で Bitmap オブジェクトを取得しようとすると ArgumentException がスローされます。下のサンプルコードでコメントアウトした部分を見てください。

ということで、Photo フィールドのバイト列を stream に変換するとき最初の 78 バイトをスキップしてやる必要があります。それは MemoryStream(Byte[], Int32, Int32) コンストラクタを使って可能です。

以下にそのサンプルコードを載せておきます。上の画像の Photo を表示するのに使った HTTP ジェネリックハンドラで、Employees テーブルの Photo データを取得して、最初の 78 バイトをスキップして MemoryStream を作り、new Bitmap(stream) で Bitmap オブジェクトを取得し、Bitmap.Save メソッドで jpg 形式にして HTTP 応答ストリームに書き込んでいます。

using System.Web;
using System.Web.Configuration;
using System.Data.SqlClient;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;

namespace WebApplication1
{
    public class EmployeePhotoHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            string id = context.Request.QueryString["id"];
            context.Response.ContentType = "image/jpeg";
            byte[] phote;
            int employeeId;
            if (!string.IsNullOrEmpty(id) && int.TryParse(id, out employeeId))
            {
                var connString = WebConfigurationManager
                    .ConnectionStrings["NORTHWINDConnectionString"]
                    .ConnectionString;
                var query = "SELECT photo FROM Employees WHERE EmployeeID = @ID";
                using (var connection = new SqlConnection(connString))
                {
                    using (var command = new SqlCommand(query, connection))
                    {
                        command.Parameters.AddWithValue("@ID", employeeId);
                        connection.Open();
                        phote = (byte[])command.ExecuteScalar();
                    }
                }

                // これはダメ
                // new Bitmap(stream) で ArgumentException がスローされる
                // "使用されたパラメーターが有効ではありません。"
                //using (var stream = new MemoryStream(phote))
                //{
                //    using (var bitmap = new Bitmap(stream))
                //    {
                //        bitmap.Save(context.Response.OutputStream, ImageFormat.Jpeg);
                //    }
                //}

                // これは OK
                // The 78 superfluous bytes are a proprietary OLE header that Access
                // creates when saving bitmaps. ・・・ということで最初の 78 バイトは
                // スキップしないと有効な Bitmap 形式とはみなされないらしい
                using (var stream = new MemoryStream(phote, 78, phote.Length - 78))
                {
                    using (var bitmap = new Bitmap(stream))
                    {
                        bitmap.Save(context.Response.OutputStream, ImageFormat.Jpeg);
                    }
                }
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

Tags: , ,

SQL Server

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  June 2021  >>
MoTuWeThFrSaSu
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

View posts in large calendar