最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - How to load an image in ASP.NET from a database as a file in a web browser? - Stack Overflow

programmeradmin4浏览0评论

I have some images in a SQL Server database. I want to display them when a user clicks a button, but I want them to load into the browser as a file so that when the user resizes the window the images automatically resize.

For example in Firefox if you go to File->Open File... and select an image on your puter, it will load it into a new window and resize it for you when you drag the scrollbars. My problem is, how do I get the image to load from a SQL Server database into the browser as a file? I have the following code on the form where the user clicks view within a GridView:

<script type="text/javascript">
    function ShowImageInNewPage(url_add) {
        window.open(url_add, 'ViewScreenshot', 'resizable=yes,scrollbars = yes');
    }
</script>

<asp:GridView 
 ID="grdTrades" 
 runat="server" 

 <... removed some properties for brevity ...>
 >
 <Columns>
  <asp:CommandField ShowSelectButton="true" ButtonType="Link" SelectText="Select" /> 

  <.. removed some columns for brevity ...>

  <asp:TemplateField HeaderText="Screenshot" >
   <ItemTemplate>
    <input type="button" size="x-small" value="View" onclick="javascript:ShowImageInNewPage('DisplayImage.aspx?screenshotId=<%# Eval("screenshotId") %>');" />
   </ItemTemplate>
  </asp:TemplateField>
 </Columns>
</asp:GridView>

DisplayImage.aspx has this code:

<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {        
        if (Request.QueryString["screenshotId"] != null)
        {            
            int screenshotId= int.Parse(Request.QueryString["screenshotId"]);
            imgScreenshot.ImageUrl = "App_Handlers/ImageHandler.ashx?screenshotId=" + screenshotId;            
        }
    }    
</script>

<html>
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Image ID="imgScreenshot" runat="server" />
    </div>
    </form>
</body>
</html>

App_Handlers/ImageHandler.ashx has this code:

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

using System;
using System.Web;
using System.Data;
using DatabaseComponent;

public class ImageHandler : IHttpHandler {

    public void ProcessRequest (HttpContext context) {

        if (context.Request.QueryString["screenshotId"] != null)
        {
            int screenshotId = int.Parse(context.Request.QueryString["screenshotId"]);

            DBUtil DB = new DBUtil();
            DataTable dt = DB.GetScreenshot(screenshotId);

            if (dt != null)
            {
                Byte[] bytes = (Byte[])dt.Rows[0]["screenshot"];
                context.Response.Buffer = true;
                context.Response.Charset = "";
                context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
                context.Response.ContentType = dt.Rows[0]["contentType"].ToString();
                context.Response.AddHeader("content-disposition", "attachment;filename=" + dt.Rows[0]["fileName"].ToString());
                context.Response.BinaryWrite(bytes);               
                context.Response.Flush();
                context.Response.End();
            }
        }        
    }

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

Here are the response headers for DisplayImage.aspx

Server: ASP.NET Development Server/10.0.0.0
Date: Wed, 10 Nov 2010 13:13:37 GMT
X-AspNet-Version: 4.0.30319
Transfer-Encoding: chunked
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Content-Type: image/JPG
Connection: Close

I've changed my original question to use an image handler now thanks @leppie. Thanks for looking!

UPDATE

I've now changed DisplayImage.aspx to this code, but now I get some real weird behavior. When I click on an image link, this page loads and firefox asks if I want to save DisplayImage.aspx. What is going on? How can I get Firefox to load the image as a file?

DisplayImage.aspx:

<%@ Page Language="C#" ContentType="image/*"  %>

<script runat="server">        
</script>

<html>
<head runat="server">
    <title></title>
</head>
<body>
    <img  src="App_Handlers/ImageHandler.ashx?screenshotId=<%=Request.QueryString["screenshotId"]%>" /> 
</body>
</html>

If I remove ContentType from the Page declaration the image loads into a new window however the image won't zoom, and won't resize itself. Pulling my hair out...

I have some images in a SQL Server database. I want to display them when a user clicks a button, but I want them to load into the browser as a file so that when the user resizes the window the images automatically resize.

For example in Firefox if you go to File->Open File... and select an image on your puter, it will load it into a new window and resize it for you when you drag the scrollbars. My problem is, how do I get the image to load from a SQL Server database into the browser as a file? I have the following code on the form where the user clicks view within a GridView:

<script type="text/javascript">
    function ShowImageInNewPage(url_add) {
        window.open(url_add, 'ViewScreenshot', 'resizable=yes,scrollbars = yes');
    }
</script>

<asp:GridView 
 ID="grdTrades" 
 runat="server" 

 <... removed some properties for brevity ...>
 >
 <Columns>
  <asp:CommandField ShowSelectButton="true" ButtonType="Link" SelectText="Select" /> 

  <.. removed some columns for brevity ...>

  <asp:TemplateField HeaderText="Screenshot" >
   <ItemTemplate>
    <input type="button" size="x-small" value="View" onclick="javascript:ShowImageInNewPage('DisplayImage.aspx?screenshotId=<%# Eval("screenshotId") %>');" />
   </ItemTemplate>
  </asp:TemplateField>
 </Columns>
</asp:GridView>

DisplayImage.aspx has this code:

<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {        
        if (Request.QueryString["screenshotId"] != null)
        {            
            int screenshotId= int.Parse(Request.QueryString["screenshotId"]);
            imgScreenshot.ImageUrl = "App_Handlers/ImageHandler.ashx?screenshotId=" + screenshotId;            
        }
    }    
</script>

<html>
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Image ID="imgScreenshot" runat="server" />
    </div>
    </form>
</body>
</html>

App_Handlers/ImageHandler.ashx has this code:

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

using System;
using System.Web;
using System.Data;
using DatabaseComponent;

public class ImageHandler : IHttpHandler {

    public void ProcessRequest (HttpContext context) {

        if (context.Request.QueryString["screenshotId"] != null)
        {
            int screenshotId = int.Parse(context.Request.QueryString["screenshotId"]);

            DBUtil DB = new DBUtil();
            DataTable dt = DB.GetScreenshot(screenshotId);

            if (dt != null)
            {
                Byte[] bytes = (Byte[])dt.Rows[0]["screenshot"];
                context.Response.Buffer = true;
                context.Response.Charset = "";
                context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
                context.Response.ContentType = dt.Rows[0]["contentType"].ToString();
                context.Response.AddHeader("content-disposition", "attachment;filename=" + dt.Rows[0]["fileName"].ToString());
                context.Response.BinaryWrite(bytes);               
                context.Response.Flush();
                context.Response.End();
            }
        }        
    }

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

Here are the response headers for DisplayImage.aspx

Server: ASP.NET Development Server/10.0.0.0
Date: Wed, 10 Nov 2010 13:13:37 GMT
X-AspNet-Version: 4.0.30319
Transfer-Encoding: chunked
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Content-Type: image/JPG
Connection: Close

I've changed my original question to use an image handler now thanks @leppie. Thanks for looking!

UPDATE

I've now changed DisplayImage.aspx to this code, but now I get some real weird behavior. When I click on an image link, this page loads and firefox asks if I want to save DisplayImage.aspx. What is going on? How can I get Firefox to load the image as a file?

DisplayImage.aspx:

<%@ Page Language="C#" ContentType="image/*"  %>

<script runat="server">        
</script>

<html>
<head runat="server">
    <title></title>
</head>
<body>
    <img  src="App_Handlers/ImageHandler.ashx?screenshotId=<%=Request.QueryString["screenshotId"]%>" /> 
</body>
</html>

If I remove ContentType from the Page declaration the image loads into a new window however the image won't zoom, and won't resize itself. Pulling my hair out...

Share Improve this question edited Nov 14, 2010 at 10:38 Mark Allison asked Nov 10, 2010 at 9:11 Mark AllisonMark Allison 7,23835 gold badges106 silver badges158 bronze badges 5
  • It seems that no-one knows how to load an image from a database and load it into the browser as a file. This must be a mon pattern, does anyone want to have another try? :-) – Mark Allison Commented Nov 14, 2010 at 7:37
  • you need to change the content-disposition header to inline and include the content-length header as well – Pauli Østerø Commented Nov 14, 2010 at 12:50
  • @leppie - it seems I don't need two pages. See my answer. – Mark Allison Commented Nov 14, 2010 at 19:05
  • The handler is a 'still a page' effectively. – leppie Commented Nov 14, 2010 at 19:21
  • @leppie, yes but I've removed both GetImage.aspx AND DisplayImage.aspx – Mark Allison Commented Nov 14, 2010 at 19:32
Add a ment  | 

4 Answers 4

Reset to default 3

You should not use a page to return the image data. Instead you should use an HttpHandler. An HttpHandler is a class that implements the IHttpHandler interface. The IHttpHandler interface is more low-level than Page. Page does in fact implement IHttpHandler itself, but the purpose of Page is to return html, which is why you should not be using it for returning image data.

If you want to do this using a page (e.g. ImageLoad.aspx) then something like this in Page_Load should suffice:

protected void Page_Load(object sender, EventArgs e)
{
    HttpResponse response = HttpContext.Current.Response;

    response.Clear();
    response.ContentType = "image/png";

    Image outputImage = (Load your image here)
    MemoryStream ms = new MemoryStream();
    outputImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
    ms.WriteTo(response.OutputStream);
    outputImage.Dispose();
    ms.Close();

    response.End();
}

Alternatively with a handler:

public class ImageHandler : IHttpHandler
{
    public bool IsReusable
    {
        get { return true; }
    }

    public void ProcessRequest(HttpContext context)
    {
        try
        {
            HttpResponse response = context.Response;

            response.Clear();
            response.ContentType = "image/png";

            Image outputImage = (Load your image here)
            MemoryStream ms = new MemoryStream();
            outputImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
            ms.WriteTo(response.OutputStream);
            outputImage.Dispose();
            ms.Close();

            response.End();
        }
        catch
        {
            context.Response.End();
        }
    }
}

Just replace (Load your image here) with the relevant code based on how you specify the image (presumably as a request parameter).

As suggested in other answers set relevant caching headers on the request if you want to save some clock cycles.

Once you have the byte[] from your database

Set the Response.MimeType to the appropriate value such as "image/jpg" for jpeg images Then do a Response.Write or Response.WriteBinary to write the byte[] out to the response.

Optionally set Caching headers if you want the browser to cache the file.

I've managed to work it out. I can remove DisplayImage.aspx pletely and just call the image handler directly from my calling page, so my GridView now looks like this:

<script type="text/javascript">
    function ShowImageInNewPage(url_add) {
        window.open(url_add, 'ViewScreenshot', 'resizable=yes,scrollbars = yes');
    }
</script>

<asp:GridView 
 ID="grdTrades" 
 runat="server" 

 <... removed some properties for brevity ...>
 >
 <Columns>
  <asp:CommandField ShowSelectButton="true" ButtonType="Link" SelectText="Select" /> 

  <.. removed some columns for brevity ...>

  <asp:TemplateField HeaderText="Screenshot" >
   <ItemTemplate>
    <input runat="server" visible='<%# Eval("screenshotId") != DBNull.Value %>' type="button" value='View...' onclick='<%# "ShowImageInNewPage(\"App_Handlers/ImageHandler.ashx?screenshotId=" + Eval("screenshotId") + "\")" %>' />
   </ItemTemplate>
  </asp:TemplateField>
 </Columns>
</asp:GridView>

When the user clicks the button, the image loads into a new window and can be resized on the client by dragging the window corner. Thanks for everyone's help on this.

发布评论

评论列表(0)

  1. 暂无评论