0

私の Web アプリケーションでは、ユーザーがレポートを送信したり、データベース (SQL Server) に最大 5 つの画像を varbinary(MAX) として挿入したりできます。現在、ユーザーが送信した特定のレポートのすべての画像を取得する方法を見つけています。以前は、aspx ページから 1 つずつ画像を取得していました。しかし、ユーザーが 5 つのうち 1 つの画像のみを挿入すると、問題が発生しました。他の 4 つの画像タグには null 画像が表示されます。そのため、レポートに基づいてそれらの画像を 1 つの画像タグで取得できる方法を見つけようとしています。以前はレポートと同じテーブルに画像が保存されていましたが、今は 2 テーブルに変更しています。MemberReport はレポートのすべての詳細であり、MemberReportImage はレポートのすべての画像です。

以下のコードにより、memberreportid に基づいて MemberReportImage テーブルから最初の画像を取得して画像タグに入れることができますが、画像タグよりも同じ memberreportid を持つすべての画像を一度に取得したいと考えています。すべての画像を取得するにはループが必要だと思いますが、その方法がわかりません。だから私はこれを手伝ってくれる人が必要です。ありがとう!

protected void Page_Load(object sender, EventArgs e)
{
    string strQuery = "select image from MemberReportImage where memberreportid='" + Session["memberreportid"] + "'";
    SqlCommand cmd = new SqlCommand(strQuery);
    DataTable dt = GetData(cmd);
    if (dt != null)
    {
        download(dt);
    }
}

private DataTable GetData(SqlCommand cmd)
{
    DataTable dt = new DataTable();
    SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
    SqlDataAdapter sda = new SqlDataAdapter();
    cmd.CommandType = CommandType.Text;
    cmd.Connection = con;
    try
    {
        con.Open();
        sda.SelectCommand = cmd;
        sda.Fill(dt);
        return dt;
    }
    catch
    {
        return null;
    }
    finally
    {
        con.Close();
        sda.Dispose();
        con.Dispose();
    }
}

private void download(DataTable dt)
{
    // check if you have any rows at all 
    // no rows -> no data to convert!
    if (dt.Rows.Count <= 0)
        return;

    // check if your row #0 even contains data -> if not, you can't do anything!
    if (dt.Rows[0].IsNull("image"))
        return;

    Byte[] bytes = (Byte[])dt.Rows[0]["image"];
    Response.Buffer = true;
    Response.Charset = "";
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
    Response.ContentType = "image/jpg";
    Response.BinaryWrite(bytes);
    Response.End();
}
4

1 に答える 1

2

あなたがそこに頼んだことをする多くの例があります。この答えは 2 つの部分に分かれています。まず、(UI ページで) どの画像が存在するかを把握し、クエリの結果に基づいて画像を表示または非表示にする必要があります。次に、ページ (より適切には HttpHandler) を使用して、ページに画像を表示する必要があります。以下に簡単なサンプルをモックアップしました。コードを読みやすくするために、コードにコメントを付けてみました。

ASPx ページ (Html)

<form id="form1" runat="server">
    <div>
        <asp:Image ID="Image1" runat="server" />
        <asp:Image ID="Image2" runat="server" />
        <asp:Image ID="Image3" runat="server" />
        <asp:Image ID="Image4" runat="server" />
        <asp:Image ID="Image5" runat="server" />
    </div>
</form>

画像5枚のシンプルなページです。ページはかなり複雑になりますが、これはデモ用です。次に、ページ読み込みイベント (またはその他のイベント) を使用して、データベースから画像を検索し、アップロードされていない画像を非表示にします。

ASPx ページ (コード)

protected void Page_Load(object sender, EventArgs e)
{
    Session["memberreportid"] = 1; //TODO: Remove this
    var query = "SELECT TOP 1 * FROM  MemberReport where memberreportid=@p1";

    //create the format string for each image. Note the last variable is {0} for additional formating
    string imageSource = string.Format("/viewImage.ashx?memberreportid={0}&imageID={1}", Session["memberreportid"], "{0}");

    //set our URL to our Image handler for each image
    Image1.ImageUrl = string.Format(imageSource, 1);
    Image2.ImageUrl = string.Format(imageSource, 2);
    Image3.ImageUrl = string.Format(imageSource, 3);
    Image4.ImageUrl = string.Format(imageSource, 4);
    Image5.ImageUrl = string.Format(imageSource, 5);

    //execute our command. Note we are using parameters in our SQL to circumvent SQL injection
    using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["conString"].ConnectionString))
    {
        var cmd = new SqlCommand(query, con);
        cmd.CommandType = System.Data.CommandType.Text;
        cmd.CommandTimeout = 3000;
        cmd.Parameters.AddWithValue("@p1", Session["memberreportid"]);
        con.Open();
        var reader = cmd.ExecuteReader();
        while (reader.Read())
        {
            //hide each image if the image is null or not a byte array (should always be a byte array)

            if (reader["image1"] == null || !(reader["image1"] is byte[]))
                Image1.Visible = false;
            if (reader["image2"] == null || !(reader["image2"] is byte[]))
                Image2.Visible = false;
            if (reader["image3"] == null || !(reader["image3"] is byte[]))
                Image3.Visible = false;
            if (reader["image4"] == null || !(reader["image4"] is byte[]))
                Image4.Visible = false;
            if (reader["image5"] == null || !(reader["image5"] is byte[]))
                Image5.Visible = false;

            //we only want the first row so break (should never happen anyway)
            break;
        }
        con.Close();
    }
}

上記からわかるように、見つかった ID に基づいてアップロードされた画像を見つけるクエリを実行しているだけです。画像が null (または byte[] でない) の場合、画像コントロールは非表示になります。

最後のピースは、HttpHandler (New Item リストの GenericHandler) を使用しています。すべてのページ生成イベントを必要とせず、HttpHandler コンテキストに直接フックできるため、おそらくここでは HttpHandler が最善の策です。ここから、ASPx ページでやりたいことのほとんどすべてを行うことができます (私の個人的な実装)。デフォルトでは、HttpHandler はセッション状態にアクセスできないことに注意してください。

viewImage.ashx (または必要に応じて) という名前の新しい GenericHandler を追加し、次のコードを追加します。ここでも、読みやすくするためにコメントが付けられています。

viewImage.ashx コード。

using System;
using System.Configuration;
using System.Data.SqlClient;
using System.Web;

namespace WebApplication1
{
    /// <summary>
    /// Summary description for viewImage
    /// </summary>
    public class viewImage : IHttpHandler
    {
        /// <summary>
        /// process the request
        /// </summary>
        /// <param name="context">the current request handler</param>
        public void ProcessRequest(HttpContext context)
        {
            ///extract our params from the request
            int memberID = 0, imageID = 0;
            if (!int.TryParse(context.Request["memberreportid"], out memberID) || 
                 memberID <= 0 ||
                 !int.TryParse(context.Request["imageID"], out imageID) || 
                 imageID <= 0)
            {
                this.transmitError();
                return;
            }

            //build our query
            var query = string.Format("SELECT TOP 1 image{0} FROM  MemberReport where memberreportid=@p1", imageID);

            //execute the query
            using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["conString"].ConnectionString))
            {
                try
                {
                    var cmd = new SqlCommand(query, con);
                    cmd.CommandType = System.Data.CommandType.Text;
                    cmd.CommandTimeout = 3000;
                    //set the member command type
                    cmd.Parameters.AddWithValue("@p1", memberID);
                    con.Open();
                    var reader = cmd.ExecuteReader();
                    while (reader.Read())
                    {
                        string psudoFileName = string.Format("memberReport_{0}_image{1}.png", memberID, imageID);
                        byte[] binary = reader[0] as byte[];
                        context.Response.ContentType = "image/png";
                        context.Response.AppendHeader("Content-Disposition", string.Format("filename=\"{0}\"", psudoFileName));
                        context.Response.AppendHeader("Content-Length", binary.Length.ToString());
                        context.Response.BinaryWrite(binary);

                        //todo: Implement your caching. we will use no caching
                        context.Response.Cache.SetCacheability(HttpCacheability.NoCache);

                        //we only want the first row so break (should never happen anyway)
                        break;
                    }
                    con.Close();
                }
                catch (Exception ex)
                {
                    //TODO: Maybe some logging?

                }
                this.transmitError();   
            }
        }

        /// <summary>
        /// transmits a non-image found
        /// </summary>
        void transmitError()
        {
            var context = HttpContext.Current;
            if (context == null)
                return;
            //set the response type
            context.Response.ContentType = "image/png";
            //set as no-cache incase this image path works in the future.
            context.Response.Cache.SetCacheability(HttpCacheability.NoCache);

            //transmit the no-image found error
            context.Response.TransmitFile(context.Server.MapPath("no-image.png"));
        }

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

これで、ページに画像を表示し、アップロード時に画像を表示/非表示にするために必要なすべてのはずです。

お役に立てれば。

于 2013-09-11T03:14:16.360 に答える