2

我想在 asp:GridView 中显示“图像”列。这个想法是提供图像的缩略图,并链接到真实大小的图像。对于某些行,这可能是 PDF 文档。我希望链接到 PDF。PDF 或图像存储在 SQL 数据库中。

现在我在处理程序(.ashx)文件中有错误:

“不存在数据时尝试读取无效。”

这是我的代码:

ASP:

<asp:GridView ID="GridView1" runat="server" 
            AutoGenerateColumns="False" DataKeyNames="ID"
            DataSourceID="SqlDataSource1">
   <Columns>
      <asp:BoundField DataField="assessment_id" HeaderText="assessment_id" 
                    InsertVisible="False" ReadOnly="True"
                    SortExpression="assessment_id" />
      <asp:BoundField DataField="a_mime" HeaderText="a_mime" SortExpression="a_mime" />
      <asp:TemplateField HeaderText="a_data">       
        <ItemTemplate>
        <asp:Image ID="Image1" runat="server" ImageUrl='<%# "Handler.ashx?ID=" + Eval("ID")%>'/>
        </ItemTemplate>
      </asp:TemplateField>
  </Columns>
</asp:GridView>

<asp:SqlDataSource ID="SqlDataSource1" runat="server" 
  ConnectionString="<%$ ConnectionStrings:testConnectionString %>"
  SelectCommand="SELECT [assessment_id], [a_data], [a_mime] FROM [Assessments]">    
</asp:SqlDataSource>

处理程序 ASHX:

<%@ WebHandler Language="C#" Class="Handler" %>

public class Handler : IHttpHandler {

public void ProcessRequest (HttpContext context) 
{
    SqlConnection con = new SqlConnection();
    con.ConnectionString = ConfigurationManager.ConnectionStrings["testConnectionString"].ConnectionString;

    // Create SQL Command 
    SqlCommand cmd = new SqlCommand();
    cmd.CommandText = "Select a_data from Assessments where assessment_id =@ID";
    cmd.CommandType = System.Data.CommandType.Text;
    cmd.Connection = con;

    SqlParameter ImageID = new SqlParameter("@ID", System.Data.SqlDbType.Int);
    ImageID.Value = Convert.ToInt32(context.Request.QueryString["assessment_id"]);
    cmd.Parameters.Add(ImageID);
    con.Open();

    SqlDataReader dReader = cmd.ExecuteReader();
    dReader.Read();

    context.Response.BinaryWrite((byte[])dReader["a_data"]);

    dReader.Close();

    con.Close();
}

如果可能,请帮助我。如果耗时,请提供示例或博客文章的链接。

4

1 回答 1

1

错误的原因Invalid attempt to read when no data is present是因为 DataReader 不包含任何记录(没有给定 ID 的图像)。考虑将您的代码更改为:

SqlDataReader dReader = cmd.ExecuteReader();

if (dReader.HasRows)
{
  while (dReader.Read())
  {
     context.Response.BinaryWrite((byte[])dReader["a_data"]);
  }

  dReader.Close();
}

几点改进建议

  • 尝试预测一行何时没有图像
  • 当您可以在 ASP.NET 页面上检测到时,执行对 .ashx 页面的调用
  • 当您可以检测到需要呈现 PDF 的链接时,显示一个漂亮的静态 pdf 图像,其链接将是 URL。

考虑在可能的情况下检查给定的评估是否具有所需的图像或 PDF。也许添加一个 where 子句以某种方式确定此记录是否需要显示 PDF 或图像场景。

我还可以建议您将您的 SQL 语句转换为存储过程,如上所述,并修改您的 SqlDataSource 如下:

CREATE PROC ListAssessments
AS

SELECT [assessment_id]
     , [a_data]
     , [a_mime] 
     , CASE WHEN a_mime = 'PDF' THEN 1
       ELSE 0
       END AS IsPDF

FROM Assessments  

现在在您的 Gridview 上,您可以确定是要渲染图像还是 PDF 链接。

<asp:TemplateField HeaderText="Image">       
  <ItemTemplate>
     <asp:PlaceHolder id="ph1" runat="server" />    
  </ItemTemplate>
</asp:TemplateField>

将您的 Gridview 设置为具有调用您可以编写的新方法的 ItemDataBound 事件。

<asp:GridView OnRowDataBound="ShowImageOrPdf" 

然后,在您的代码隐藏中,您可以确定要在该占位符中呈现哪个 web 控件。

protected void ShowImageOrPdf(object sender, GridViewRowEventArgs e)
{
    const string LINK = "handler.ashx?Id={0}&Type={1}";
    GridView gv = (GridView)sender;

    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        string assessmentID = gv.DataKeys[e.Row.RowIndex].Value.ToString();
        bool isPDF =  (bool)e.Row.DataItem["IsPDF"];
        HyperLink h = new HyperLink();

        if (isPDF)
        {
            //render a link showing that it's a PDF.
            h.NavigateUrl = string.Format(LINK, assessmentID, "PDF");
            h.ImageUrl = "http://www.adobe.com/images/pdficon_large.gif";
            h.Text = "View PDF";
        }
        else
        {
            //render a thumbnail with a link to the image
            h.NavigateUrl = string.Format(LINK, assessmentID, "IMG");

            //have the handler create a thumbnail somehow.
            h.ImageUrl = string.Concat(h.NavigateUrl + "&Size=Small");
        } 
       //write the link back to the placeholder.
       e.Row.FindControl("ph1").Controls.Add(h);
    }
}

然后在您的 中.ashx,您必须读取查询字符串参数以确定要输出的内容:图像、缩略图或存储在数据库中的 PDF 文档。

于 2009-11-29T04:20:22.123 回答