views:

3714

answers:

5

I have a function which extracts a file into a byte array (data).

        int contentLength = postedFile.ContentLength;
        byte[] data = new byte[contentLength];
        postedFile.InputStream.Read(data, 0, contentLength);

Later I use this byte array to construct an System.Drawing.Image object (where data is the byte array)

       MemoryStream ms = new MemoryStream(data);
       Image bitmap = Image.FromStream(ms);

I get the following exception "ArgumentException: Parameter is not valid."

The original posted file contained a 500k jpeg image...

Any ideas why this isnt working?

Note: I assure you I have a valid reason for converting to a byte array and then to a memorystream!!

+1  A: 

You're not checking the return value of postedFile.InputStream.Read. It is not at all guaranteed to fill the array on the first call. That will leave a corrupt JPEG in data (0's instead of file content).

Matthew Flaschen
A: 

I have had problems loading images in .NET that were openable by more robust image libraries. It's possible that the specific jpeg image you have is not supported by .NET. jpeg files are not just one type of encoding, there's a variety of possible compression schemes allowed.

You could try it with another image that you know is in a supported format.

Eclipse
+1  A: 

Have you checked the return value from the Read() call to verify that is actually reading all of the content? Perhaps Read() is only returning a portion of the stream, requiring you to loop the Read() call until all of the bytes are consumed.

Kevin Pullin
+4  A: 

That's most likely because you didn't get all the file data into the byte array. The Read method doesn't have to return as many bytes as you request, and it returns the number of bytes actually put in the array. You have to loop until you have gotten all the data:

int contentLength = postedFile.ContentLength;
byte[] data = new byte[contentLength];
for (int pos = 0; pos < contentLength; ) {
   pos += postedFile.InputStream.Read(data, pos, contentLength - pos);
}

This is a common mistake when reading from a stream. I have seen this problem a lot of times.

Edit:
With the check for an early end of stream, as Matthew suggested, the code would be:

int contentLength = postedFile.ContentLength;
byte[] data = new byte[contentLength];
for (int pos = 0; pos < contentLength; ) {
   int len = postedFile.InputStream.Read(data, pos, contentLength - pos);
   if (len == 0) {
      throw new ApplicationException("Upload aborted.");
   }
   pos += len;
}
Guffa
Used the suggested code: int contentLength = postedFile.ContentLength; byte[] data = new byte[contentLength]; for (int pos = 0; pos < contentLength; pos++) { pos += postedFile.InputStream.Read(data, pos, contentLength - pos); } return data;Still didnt work!
ListenToRick
You should also check for a 0 return, just in case you hit end of stream early.
Matthew Flaschen
Isnt 0 a valid value?
ListenToRick
@ListenToRick: You have put an extra p++ in the for statement that should not be there. That will make a one byte gap between the blocks of data that you read.
Guffa
Had a thought.... In a previous function I have read header information from the stream. This happens to be 4 bytes (i'm checking for a jpg). The amount of data read from the stream and passed to the file is missing 4 bytes!!!STUPID STUPID STUPID!!
ListenToRick
@ListenToRick, 0 will only be returned when end of stream is reached. For your sniffing problem, you will basically want to remember the 4 bytes, copy them into data (which can be created only when you're sure you have a JPEG), and set pos appropriately.
Matthew Flaschen
A: 

Any reason why you don't simply do this:

Image bitmap = Image.FromStream(postedFile.InputStream);
jrista
> Note: I assure you I have a valid> reason for converting to a byte array> and then to a memorystream!!
Snarfblam