views:

437

answers:

3

Hello,

I am developing a web application that calls web services developed by a third party to send/receive data from a clients database. I am building the application using ASP.NET 3.5 C#.

The way that they are providing me images is in BLOB format. I call their method and what I get back is a DataSet with 2 fields "logo_name" and "logo" which is the BLOB field. What I want to do is: Save the image locally on the disk (to minimize calls to their database in the future).

I have been playing around with a couple of different ways of doing this but cannot seem to get the image to save correctly. I have been able to create a file in a folder with the correct name but if I try to view the image it does not work.

I was hoping someone could give me some sample code to show me how to save a BLOB field to the local disk?

Here is the code I currently have

public static class ProductImages
    {


        public static string GetSchoolLogo(string schoolID, string printCodeID)
        {
            int v_length = 0;
            string v_file_name = "";
            byte[] v_file_data = null;

            try
            {

                //Declare Web Service Variables
                P_SERVICE.Service ldeService = new P_SERVICE.Service();
                //Authentication Header
                ldeService.AuthHeaderValue = CGlobal.GetAuthHeader(System.Web.HttpContext.Current.Session);
                P_SERVICE.CDataResultOfDataSet ldeResult = null;
                DataSet ds = new DataSet();

                ldeResult = ldeService.GetItemLogo(schoolID, printCodeID);
                ds = ldeResult.Value;

                if (ds.Tables[0].Rows.Count > 0)
                {
                    v_file_data = StrToByteArray(ds.Tables[0].Rows[0]["logo"].ToString().TrimEnd());
                    v_file_name = ds.Tables[0].Rows[0]["logo_name"].ToString().TrimEnd();
                    v_length = Convert.ToInt32(v_file_data.Length);

                    // Load the file in the Memory Stream
                    MemoryStream ms = new MemoryStream(v_file_data, 0, v_file_data.Length);
                    ms.Write(v_file_data, 0, v_file_data.Length);

                    // Open the file stream in ordre to save on the local disk
                    string path = HttpContext.Current.Server.MapPath("~/_imagecache/schoolLogos/").ToString();
                    FileStream fs = File.OpenWrite(path + schoolID + "/" + v_file_name);
                    fs.Write(v_file_data, 0, v_file_data.Length);
                    fs.Close();

                    // Return True if no errors occured
                    return "~/_imagecache/schoolLogos/" + schoolID + "/" + v_file_name;
                }
                else
                    return "~/images/noPhoto.gif";

           }

            catch (Exception ex)
            {

                throw new Exception(ex.Message.ToString());
                //return "~/images/noPhoto.gif";
            } 
        }

        // C# to convert a string to a byte array.
        public static byte[] StrToByteArray(string str)
        {
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            return encoding.GetBytes(str);
        }
    }


}

When I get the Type of data being returned it returns System.String

Type t = ds.Tables[0].Rows[0]["logo"].GetType();
HttpContext.Current.Trace.Warn(t.FullName);

Thanks

+2  A: 

Your line:

v_file_data = StrToByteArray(ds.Tables[0].Rows[0]["logo"].ToString().TrimEnd()); 

Should really be:

v_file_data = ds.Tables[0].Rows[0]["logo"] as Byte[];

The method you were using will not encode and decode the bytes in the same way.

ck
Granted, the StrToByteArray is hinky, but perhaps the image is coming in Base64?
Sky Sanders
I changed that line in my code but am getting a null reference exception..
TGuimond
A: 

Try this:

// replace this line:
//v_file_data = StrToByteArray(ds.Tables[0].Rows[0]["logo"].ToString().TrimEnd());

// with this block:
string base64string = ds.Tables[0].Rows[0]["logo"] as string;

if (base64string != null)
{
    v_file_data = System.Convert.FromBase64String(v_file_data);
}

Take the byte array and load it to file using the rest of your code.

HTH....

code4life
+1  A: 

Ok, so it looks like the web service is doing you no favors. They really should be returning a byte array. but anyway, the string is definitely not base64 and definitely not ascii.

Lets try this wild stab in the dark:

v_file_data = Encoding.UTF8.GetBytes(ds.Tables[0].Rows[0]["logo"]);
Sky Sanders
I tried that but I am getting the same result. Image file being created, correctly named and path being returned correctly but not displaying and when I try to open in any editor it gives an unknown file type error. Image size even seems correct.
TGuimond
@sky: Note: I added a `ToString()` as it was giving me an error without it:`v_file_data = Encoding.UTF8.GetBytes(ds.Tables[0].Rows[0]["logo"].ToString());`
TGuimond
@TGui - hint: 'an error' doesn't give much to work with. At least give the error type. Ok, so try `v_file_data = Encoding.UTF8.GetBytes(((string)ds.Tables[0].Rows[0]["logo"]));`
Sky Sanders
@sky - Cheers. The error was `The best overloaded method match for 'System.Text.Encoding.GetBytes(char[])' has some invalid arguments`.Also, I tried the last line of code and am getting the same result. Image file created, correct name, etc.
TGuimond
@sky - I could probably ask the developers of the webservice to alter the service to give me a byte array instead.. I really appreciate the time you spent trying to figure this out for me.
TGuimond
@TGui - yeah, this is an odd one. You might suggest to them to also provide a usage example. I don't let a bit out the door without a working skeleton example. It is just bad form. Good luck.
Sky Sanders
@sky - Will do. Thanks again.
TGuimond
@sky - The developers finally came back with a working example and all is well.
TGuimond