ASP.NET - Отображение изображений и PDF-файлов в формате сетки

StackOverflow https://stackoverflow.com/questions/1814148

Вопрос

Я хочу отобразить в asp: GridView столбец "Изображения".Идея состоит в том, чтобы предоставить миниатюры изображения со ссылкой на изображение реального размера.Для некоторых строк это может быть альтернативный PDF-документ.Я бы хотел, чтобы ссылка была на PDF-файл.PDF-файл или изображение хранятся в базе данных SQL.

Теперь у меня ошибка в файле Handler (.ashx):

"Недопустимая попытка чтения при отсутствии данных".

Это мой код :

АСПИД:

<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();
}

Если это возможно, пожалуйста, помогите мне.Если это отнимает много времени, пожалуйста, предоставьте ссылку на пример или запись в блоге.

Это было полезно?

Решение

Причина ошибки о Invalid attempt to read when no data is present это потому, что DataReader не содержит никаких записей (нет изображения для данного идентификатора).Подумайте о том, чтобы изменить свой код на:

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" 

Затем в своем коде вы можете определить, какой webcontrol отображать в этом заполнителе.

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-документ, хранящийся в базе данных.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top