ASP.NET - Отображение изображений и PDF-файлов в формате сетки
Вопрос
Я хочу отобразить в 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-документ, хранящийся в базе данных.