Tech Off Thread

7 posts

Image.FromStream - Parameter is not valid. HELP!

Back to Forum: Tech Off
  • steinster

    Hi!

    I started out to create a simple (but cool) image uploader.
    I created a new web project just to test and got it working.

    I then copied the code over to my real web app, and guess what; it didnt work!

    I upload the exact same picture from both applications, but only the one from my test project can be displayed.
    If I try to display a picture uploaded from the real app in my test project I also get the "Parameter is not valid" when doing Image.FromStream().

    So I guess there's something happening when it writes the data to the db, but I just cant find out what. Its the exact same code in both web apps.

    Heres some code;

    From my test app:

    private void SaveImageToDb(Stream imgStream, string contentType, int byteLength) {
        string sql = "INSERT INTO sysTmpImg_TempImage (sysTmp_recno, sysTmp_contentType, sysTmp_image) VALUES(@recno,  contentType, @image)";

        SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["myPetDb"].ConnectionString);
        SqlCommand com = new SqlCommand(sql, conn);

        byte[] biImage = new byte[byteLength];
        imgStream.Read(biImage, 0, byteLength);

        com.Parameters.Add(new SqlParameter("@recno", Session.SessionID));
        com.Parameters.Add(new SqlParameter("@contentType", contentType));
        com.Parameters.Add(new SqlParameter("@image", biImage));

        if (conn.State != ConnectionState.Open) {
            conn.Open();
        }

        com.ExecuteNonQuery();

        conn.Close();
        com.Dispose();
        imgStream.Dispose();

        LoadImage(Session.SessionID);
    }

    (load image just loads the uploaded image)

    From my real app;

    public void AddNewTempImage(int usRecno, string tmpRecno, Stream imageStream, string contentType, int byteLength) {
        byte[] byteImage = new byte[byteLength];
        imageStream.Read(byteImage, 0, byteLength);

        string sql = "INSERT INTO sysTmpImg_TempImage (sysTmp_recno, sysTmp_US_recno, sysTmp_contentType, sysTmp_image) VALUES(@tmpRecno, @usRecno, @contentType, @image)";

        SqlCommand com = DataHelper.GetCommand(sql);
        com.Parameters.Add(new SqlParameter("@tmpRecno", tmpRecno));
        com.Parameters.Add(new SqlParameter("@usRecno", usRecno));
        com.Parameters.Add(new SqlParameter("@contentType", contentType));
        com.Parameters.Add(new SqlParameter("@image", byteImage));

        DataHelper.ExecuteNonQuery(com);

        imageStream.Dispose();
    }

    I'll even throw in the code for the DataHelper object;

    internal static class DataHelper
    {
        public static DataSet Execute(SqlCommand command) {
            DataSet result = new DataSet();
            SqlDataAdapter adap = new SqlDataAdapter(command);
            adap.Fill(result);

            return result;
        }

        public static void ExecuteNonQuery(SqlCommand command) {
            CheckConnection(command.Connection);

            command.ExecuteNonQuery();
            command.Connection.Close();
        }

        public static object ExecuteScalar(SqlCommand command) {
            object result = null;
            CheckConnection(command.Connection);
            result = command.ExecuteScalar();
            command.Connection.Close();

            return result;
        }

        public static SqlCommand GetCommand() {
            return GetCommand(string.Empty);
        }

        public static SqlCommand GetCommand(string commandText) {
            SqlCommand result = new SqlCommand(commandText, GetConnection());
            //result.CommandType = CommandType.Text;

            return result;
        }

        private static void CheckConnection(SqlConnection connection) {
            if (connection.State == ConnectionState.Closed) {
                connection.Open();
            }
        }

        private static SqlConnection GetConnection() {
            ConnectionStringSettings connString = ConfigurationManager.ConnectionStrings["mainDb"];

            return new SqlConnection(connString.ConnectionString);
        }
    }

    Even though Im using the datahelper, the result should be the same...

    I've created a generic handler to display the pictures and this is the line where it fails;
    System.Drawing.Image img = System.Drawing.Image.FromStream(ms);

    I could also include the code for the handlers, but since none of them can display anything I upload from my real app (but from my test app) I think the problem must be somewhere in the saving of the images.
    I've checked the bytes and they match up in length from both the apps.

    Any ideas ? I've been searching for answers for hours and now the sun is starting to come up so maybe I should get some sleep before I go crazy

  • Dexter

    Overall the code looks ok but what bugs me is the way you read data from the stream:

    1) This code expects the stream Position to be correct (probably 0). Is that always the case? Maybe you accidentally passed in a stream that's positioned at the end?
    2) You don't check the result of the Stream.Read call. Depending on what type is that stream it is possible that Read returns after reading less that the requested number of bytes.

  • steinster

    Dexter said:
    Overall the code looks ok but what bugs me is the way you read data from the stream:

    1) This code expects the stream Position to be correct (probably 0). Is that always the case? Maybe you accidentally passed in a stream that's positioned at the end?
    2) You don't check the result of the Stream.Read call. Depending on what type is that stream it is possible that Read returns after reading less that the requested number of bytes.

    yeah I'll check the stream a little more.

    but what bugs me the most is that the code works in one app but not the other.

    the only difference is that I dont declare the connection but get it from another object.

    I'll start out to duplicate exactly the code and see if it works, and then look at the stream

  • littleguru

    Hmmm... your example is very much incomplete. You show us how you save the stream into the database and then one line that loads the stream, whereas it's not clear where that stream comes from and how you read the data etc...

  • W3bbo

    littleguru said:
    Hmmm... your example is very much incomplete. You show us how you save the stream into the database and then one line that loads the stream, whereas it's not clear where that stream comes from and how you read the data etc...
    Whilst unrelated to the problem at hand, I'd advise against storing the images in the database directly since it means the database server needs to process a (relativly) large amount of data, it's usually better to store them in a filesystem where accessing it often has lower overheads in the web image hosting scenario, which I'm guessing is what you're doing?

  • AndyC

    W3bbo said:
    littleguru said:
    *snip*
    Whilst unrelated to the problem at hand, I'd advise against storing the images in the database directly since it means the database server needs to process a (relativly) large amount of data, it's usually better to store them in a filesystem where accessing it often has lower overheads in the web image hosting scenario, which I'm guessing is what you're doing?
    Unless you're using SQL Server 2008, which has a FILESTREAM type that handles that for you and gives you the advantage of storing in the database.

  • littleguru

    AndyC said:
    W3bbo said:
    *snip*
    Unless you're using SQL Server 2008, which has a FILESTREAM type that handles that for you and gives you the advantage of storing in the database.
    Yeah. I was about to mention the same... SQL Server 2008 has a nice construct that helps with that. Also, if you store them as blobs in the DB you are also fine. Blobs are made for storing large binary data and therefore I can't see why not to use them for the task.

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.