Save/Read Image To/From DB

Posts   
 
    
xc_lw2000
User
Posts: 48
Joined: 12-Dec-2006
# Posted on: 13-Apr-2007 08:10:05   

HI. I use a page(Image.aspx) to show images which is stored in db as a image field.


    protected void Page_Load(object sender, EventArgs e)
    {
        ImagesEntity image = new ImagesEntity(Convert.ToInt32(Request.QueryString["ID"]));

        byte[] b = image.ImageData;
        Response.BinaryWrite(b);
    }

when the data is saved by SQL,this page can show this image correctly.

            byte[] b=new byte[file.InputStream.Length];
            file.InputStream.Read(b,0,(int)file.InputStream.Length);
            string strSQL = "Insert Into Images Values(@ImageName,@ImageType,@ImageData) ";
                SqlCommand cmd = new SqlCommand(strSQL, conn);
                cmd.Parameters.Add(new SqlParameter("@ImageName",Path.GetFileName(file.FileName)));
                cmd.Parameters.Add(new SqlParameter("@ImageType",file.ContentType));
                cmd.Parameters.Add(new SqlParameter("@ImageData",b));
cmd.ExecuteNonQuery();

but when the data is saved by Entity,the page can't show image correctly.

            MainMasterEntity logoImg = master.LogoImage;
            byte[] bLogo=new byte[fLogo.InputStream.Length];
            fLogo.InputStream.Read(bLogo, 0, (int)fLogo.InputStream.Length);
            logoImg.ImageData = bLogo;
            logoImg.ImageName = System.IO.Path.GetFileName(fLogo.FileName);
            logoImg.ImageType = fLogo.ContentType;
            logoImg.Save();

the page just show some unknown code,like:

#$%% ^$^"#DTW b4e00i0dfsdfl4325#@%&^%$^#%#%#$%#$%

How to resolve this problem?

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 13-Apr-2007 10:45:59   

How do you display the image?

And which LLBLGen Pro runtime library version are you using, as well as the DB type (oracle/sqlserver etc.) ?

xc_lw2000
User
Posts: 48
Joined: 12-Dec-2006
# Posted on: 16-Apr-2007 11:51:50   

Walaa wrote:

How do you display the image?

And which LLBLGen Pro runtime library version are you using, as well as the DB type (oracle/sqlserver etc.) ?

I use a page to display the image by Response.BinaryWrite when page load,just like following:


    protected void Page_Load(object sender, EventArgs e)
    {
        ImagesEntity image = new ImagesEntity(Convert.ToInt32(Request.QueryString["ID"]));

        byte[] b = image.ImageData;
        Response.BinaryWrite(b);
    }


And I use the latest version of the demo.My DB is MS SQL SERVER.

When I use trace in SQL Profile of SQL Server,the same image file,but the field value is different.


when use sql
  ImageData=0x4749463839612A011100F70000000000FFFFFFEAE4E.........
when use llblgen entity
  ImageData=0x3000780034003700340039003400360033003800............

How to resoulve this problem?

Aurelien avatar
Aurelien
Support Team
Posts: 162
Joined: 28-Jun-2006
# Posted on: 16-Apr-2007 16:50:14   

Hi,

What is the type of ImageData field in the DB ?

Thus: is it Image, or is it varbinary or something else? -- Otis

jmeckley
User
Posts: 403
Joined: 05-Jul-2006
# Posted on: 16-Apr-2007 19:05:13   

2 thoughts

  1. What is the DataType of Image Data? Is it a string, or a binary field. You may just need to use Reponse.Write(Image.ImageData) with the appropiate headers.

  2. for a faster load time on your images use an ASHX file instead of an ASPX file. ASPX has the overhead of generating form tags/scripts. An ASHX is like a blank slate so you control everything. here is a quick snippet if you want to give it a try

<%@ webhandler language="C#" class="GetImage" %>
using System; 
using System.Web; 
public class NWEmpPhotoHandler : IHttpHandler 
{ 
    public bool IsReusable { get { return true; } } 
    
    public void ProcessRequest(HttpContext ctx) 
    { 
        byte[] b;
        try
        {
             int id = (int)ctx.Request.QueryString["ID"]; 
             ImagesEntity image = new ImagesEntity(id);
             b = image.ImageData;
         }
         catch
         {
            //load "image not available" image (from file or db)
         }

        ctx.Response.ContentType = "image/bmp"; 
        ctx.Response.OutputStream.Write(b, 78, b.Length - 78); 
    } 
}

**note **: outputstream.write removes the first 78 bytes for bmps. this may also correct your problem.

now when you want to reference this image use

<img src="GetImage.ashx?id=1" />
//or
Response.Redirect("GetImage.ashx?id=1");
//or
HyperLink.NavigateUrl = "GetImage.ashx?id=1";

or any other way of referencing a url in asp.net/html

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 16-Apr-2007 19:07:57   

Additionally, when you set the imagedata field to bLogo's contents, is the contents of that bytearray indeed also 0x30007800.... ? The data you're saving looks like unicode ascii text. Could you enable tracing on the DQE in the web.config file? (See 'troubleshooting and debugging' in the manual for details on this). You then should get the trace info in the vs.net output window if you run the webapp using the debugger. (F5)

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 16-Apr-2007 20:37:10   

I can't reproduce it:


namespace Tester
{
    public partial class Form1 : Form
    {
        #region Class Member Declarations
        private EmployeeEntity _toEdit;
        #endregion

        public Form1()
        {
            InitializeComponent();
        }

        private void _getPictureButton_Click(object sender, EventArgs e)
        {
            _toEdit = new EmployeeEntity(Convert.ToInt32(textBox1.Text));
            if(_toEdit.IsNew)
            {
                MessageBox.Show("Not found!");
                return;
            }

            MemoryStream stream = new MemoryStream(_toEdit.Photo);
            try
            {
                Bitmap toShow = new Bitmap(stream);
                _thePicture.Image = toShow;
            }
            catch
            {
                //nothing
            }
        }

        private void _loadNewPicture_Click(object sender, EventArgs e)
        {
            DialogResult result = _pictureFilenameOFD.ShowDialog(this);
            if(result != DialogResult.OK)
            {
                return;
            }

            FileStream stream = new FileStream(_pictureFilenameOFD.FileName, FileMode.Open);
            byte[] bytes = new byte[stream.Length];
            stream.Read(bytes, 0 ,(int)stream.Length);
            stream.Close();

            _toEdit.Photo = bytes;
            _toEdit.Save();
        }
    }
}

When I store a new picture in the image field, and load the entity again, it shows hte picture in the picturebox so the image was saved correctly.

Frans Bouma | Lead developer LLBLGen Pro
xc_lw2000
User
Posts: 48
Joined: 12-Dec-2006
# Posted on: 17-Apr-2007 04:47:11   

My doubt is why save the same file(abc.gif),get different datavalue when use different method. when use original sql sentence,I get a sql sentence like:

  (pseud code)   insert into Images values(@imagedata)   @imagedata=0x4749463839612A011100F70000000000FFFFFFEAE4E.........

when use a llblgen entity,I get a sql sentence like

   (pseud code)   insert into Images value(@imagedata) @imagedata=0x3000780034003700340039003400360033003800............

Is the llblgen do some covert to the byte[] field's value before save an entity or when set a byte[] field's value?

Sience the datavalue is different,can it load the field correctly?

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 17-Apr-2007 10:13:13   

I don't think so, LLBLGen Pro treat a field according to its database dataType and the corresponding .NET dataType, and whether there is a TypeConverter used or not.

So what's the database dataType of that field? Are you using a TypeConverter on the field? Have you tried any of the samples posted before in this thread?

xc_lw2000
User
Posts: 48
Joined: 12-Dec-2006
# Posted on: 17-Apr-2007 10:38:21   

I think I havn't expressed my idea clearly. You may need have a try as follow: DB part: only one table in DB which has two fields: ID identifier ImageData image Web part: Creat a new website which include two pages,one is UploadImage.aspx,which include a fileupload control and two buttons.Both buttons is used bo save image to DB. Be sure you select the same image file when two buttons click.

Button1_Onclick
{
     //original sql sentence 
    "Insert into Table values........"
}
Button2_Onclick
{
    //LLBLGen Entity
   ImageEntity img=new ImageEntity()
   .....
   img.save();
}

Another page is ShowImage.aspx(.ashx),no controls in this page. This page is used to show images which are saved by UploadImage.aspx.

Page_Load
{
      ImageEntity img=new Image((int)Request.QueryString["ID"]);
      Response.Binarywrite(img.ImageData);
}

Check whether you can load all images correctly which are saved by the two buttons in UploadImage.aspx. If not,which image couldn't be load,the button1 or the button2?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 18-Apr-2007 10:53:44   

This forum uses exactly that, for attachments, which are stored inside the DB. You could have a look at the sourcecode if you want, http://www.llblgen.com/HnD (which is build with LLBLGen Pro)

The thing is: I can't reproduce what you're seeing: the data I send to the DB via the entity is correct and pulling it out of the db is also correctly working.

I do find it strange though that the byte data is different in your case, as I can't repro it. Could you please check what the contents is of the byte array BEFORE you set the entity field ImageData and also please enable DQE tracing as defined in 'troubleshooting and debugging' ?

(edit) page:


<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default4.aspx.cs" Inherits="Default4" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Image upload test</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        &nbsp;<asp:FileUpload ID="FileUpload1" runat="server" Width="594px" /><br />
        <br />
        <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" /><br />
        <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label></div>
        
        <br><br>
        Current image of Employee 1:<br>
        <img src="default17.aspx?ID=1" border="0">
    </form>
</body>
</html>


codebehind:


using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using NWTest.EntityClasses;
using NWTest.DatabaseSpecific;

public partial class Default4 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }


    protected void Button1_Click(object sender, EventArgs e)
    {
        EmployeesEntity employee = new EmployeesEntity(1);
        using(DataAccessAdapter adapter = new DataAccessAdapter())
        {
            adapter.FetchEntity(employee);
            employee.Photo = FileUpload1.FileBytes;

            adapter.SaveEntity(employee);

            Label1.Text = "Save successful";
        }
    }
}

(It's adapter, but uses the same query engine to produce the query so the code to build the query and produce parameters etc. is the same)

image displayer: (default17.aspx)


<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default17.aspx.cs" Inherits="Default17" %>

and code behind:


using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using NWTest.EntityClasses;
using NWTest.DatabaseSpecific;

public partial class Default17 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        EmployeesEntity employee = new EmployeesEntity(Convert.ToInt32(Request.QueryString["ID"]));
        using(DataAccessAdapter adapter = new DataAccessAdapter())
        {
            adapter.FetchEntity(employee);
        }

        Response.BinaryWrite(employee.Photo);
    }
}


Frans Bouma | Lead developer LLBLGen Pro