Getting binary data for images that was saved in access (like northwind 2000)
לפני כמה ימים רציתי להציג ב gridview את התמונות מטבלת categories מתוך northwind,
לכאורה הקוד הוא פשוט ביותר, והוא נראה כך:
הנה קוד ה html:
1 <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
2 <Columns>
3 <asp:BoundField DataField="CategoryName" HeaderText="Name" />
4 <asp:BoundField DataField="Description" HeaderText="Description" />
5 <asp:ImageField DataImageUrlField="CategoryId"
6 DataImageUrlFormatString="Handler1.ashx?id={0}"
7 HeaderText="Picture">
8 </asp:ImageField>
9 </Columns>
10 </asp:GridView>
אז הגדרנו grid, שיש לו שלושה עמודות,
השניים הראשונים פשוטים, הם מקושרים לעמודת ה name ולעמודת ה description,
בשורה 5 הגדרנו עמודה מסוג Image, שה url שלו מפנה ל handler (שעוד מעט נראה אותו), כשה id מתקבל מתוך ה categoryId,
כעת נראה את הקוד:
11 protected void Page_Load(object sender, EventArgs e)
12 {
13 if (!IsPostBack)
14 {
15 string connectionString = @"server=localhost;
16 initial catalog=northwind;
17 integrated security=true";
18
19 SqlConnection cnn = new SqlConnection(connectionString);
20 SqlCommand cmd = new SqlCommand("SELECT * FROM Categories", cnn);
21 cnn.Open();
22
23 SqlDataReader dr = cmd.ExecuteReader();
24 DataTable dt = new DataTable();
25 dt.Load(dr);
26 cnn.Close();
27
28 Application["data"] = dt;
29
30 GridView1.DataSource = dt;
31 GridView1.DataBind();
32 }
33 }
מתחברים ל database שולפים את טבלת categories,
יוצרים את הטבלה מתוך ה reader, ומחברים את ה gridview, לטבלה.
כעת נראה את ה handler:
34 [WebService(Namespace = "http://tempuri.org/")]
35 [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
36 public class Handler1 : IHttpHandler
37 {
38
39 public void ProcessRequest(HttpContext context)
40 {
41 DataTable dt = (DataTable)context.Application["data"];
42
43 string expression = string.Format("CategoryId = {0}",
44 context.Request["id"]);
45 DataRow row = dt.Select(expression)[0];
46 byte[] array = (byte[])row.ItemArray[3];
47
48
49 context.Response.ContentType = "image/bmp";
50 context.Response.OutputStream.Write(array, 0, array.Length);
51 }
52
53 public bool IsReusable
54 {
55 get { return false; }
56 }
57 }
58 }
המתודה החשובה היא ProcessRequest,
שולפים מתוך ה Application את ה dataTable,
שולפים מתוך הטבלה את הרשומה לפי ה CategoryId
לוקחים את המערך הבינארי מהעמודה השלישית.
משנים את ה ContextType
וכותבים את המערך ל Response.
עד כאן הכל רגיל, אבל..
הנה התוצאה:
מה קרה, לכאורה הקוד שכתבנו, צריך לעבוד ?
התשובה טמונה, בזה שה database שלי היה מ 2000 שה northwind שלו, נלקח מאקסס, ולא שוכתב מחדש כמו ב 2005,
ובאקסס כל מידע בינארי נשמר כ OLE שזה מוסיף לתחילת המערך 78 בתים שהם ה header של OLE,
ולכן הקוד שלנו צריך להיראות כך:
1 public void ProcessRequest(HttpContext context)
2 {
3 DataTable dt = (DataTable)context.Application["data"];
4
5 string expression = string.Format("CategoryId = {0}",
6 context.Request["id"]);
7 DataRow row = dt.Select(expression)[0];
8 byte[] array = (byte[])row.ItemArray[3];
9
10
11 context.Response.ContentType = "image/bmp";
12 context.Response.OutputStream.Write(array, 78, array.Length - 78);
13 }
שימו לב לשורה 12: (אנחנו מתעלמים מ 78 הבתים הראשונים)
וכשנריץ נקבל את התוצאה המבוקשת: