Link to home
Start Free TrialLog in
Avatar of RecipeDan
RecipeDan

asked on

Create a Thumbnail from image after upload

Hello:

I am trying to create a thumbnail from an image after it is uploaded. I am getting an error: An exception of type 'System.IO.FileNotFoundException' occurred in System.Drawing.dll but was not handled in user code.

           HttpFileCollection hfc = Request.Files;
            for (int i = 0; i < hfc.Count; i++)
            {
                HttpPostedFile hpf = hfc[i];
                string strFilename = Path.GetFileName(hpf.FileName);
                Image image = Image.FromFile(strFilename);
                Image thumb = image.GetThumbnailImage(100, 100, () => false, IntPtr.Zero);
                string strFilenameThumb = Path.ChangeExtension(strFilename, "thumb");
	    }

Open in new window

Avatar of LordWabbit
LordWabbit

Image image = Image.FromFile(strFilename);

Open in new window

loads an image from disk, since this is server side code it is trying to load a file from the full path of strFileName
however
string strFilename = Path.GetFileName(hpf.FileName);

Open in new window

is only extracting the file name of the file instead of the full file path.  Not sure where your files are being stored and the attempt to access them is, but clearly they are not the same default locations.  I would suggest setting breakpoints on both and seeing if they FULL absolute paths match, this will probably tell you why using the relative paths is giving you a file not found error and you can adjust the relative paths respectively so that they DO match.
Just noticed something, the Request.Files are the files in the request collection in MIME format, they are not written to disk yet.  The Image.FromFile is reading from disk, it expects there to be a physical file.  You either need to write the files to disk first (terrible idea) or create the image from a stream.
            // create an array of the appropriate size to house the stream
            byte[] byteMe = new byte[Request.Files[0].InputStream.Length];
            // load the stream of butes into the array
            Request.Files[0].InputStream.Read(byteMe, 0, (int)Request.Files[0].InputStream.Length);
            // create a memory stream and using that create an image
            System.Drawing.Image img = System.Drawing.Image.FromStream(new System.IO.MemoryStream(byteMe));
            // back to your code to create a thumbnail
            System.Drawing.Image thumb = img.GetThumbnailImage(100, 100, () => false, IntPtr.Zero);

Open in new window

Not sure what you want to do with the thumbnail afterwards?  
The reason I mention writing to disk being a terrible idea only applies if you actually don't want to keep the full image.  Writing to disk to 'bridge' the gap between two seperate functions is bad, then you have to write garbage collection routines etc. etc. or in a few days/weeks/months you run out of disk space due to unwanted images.
Also notice that for Image I had to use the fully qualified name as at this point there is a class name conflict between namespaces.
Avatar of kaufmed
Avatar of RecipeDan

ASKER

My apologies, I just saw that I didn't copy and paste all of my code. I am uploading my files to a Blob on Azure. The code below works for the upload. I tested both of your codes and they work. How would I get the filename of the new thumbnail image and upload to the blob?

            HttpFileCollection hfc = Request.Files;
            for (int i = 0; i < hfc.Count; i++)
            {
                HttpPostedFile hpf = hfc[i];
                string trainingfolder = "Dan"
                string strFilename = Path.GetFileName(hpf.FileName);

                CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
                CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
                CloudBlobContainer container = blobClient.GetContainerReference(trainingfolder);
                CloudBlockBlob blockBlob = container.GetBlockBlobReference(strFilename);
                blockBlob.Properties.ContentType = hpf.ContentType;
                blockBlob.UploadFromStream(hpf.InputStream);
            
            }

Open in new window

hpf.FileName is the filename, so if I uploaded an image C:\Images\LordWabbit.jpg the value in hpf.FileName would be LordWabbit.jpg.  Doing a Path.GetFileName(hpf.FileName) on that would do nothing and return LordWabbit.jpg.
Correct. I understand that part of it. What I do not know is how to upload an image to a blob created on a server. The example I gave above uploads the file from a direct path. The same script does not work with files like the thumbnails that are created on a server.
I wrote this code below. It uploads a file to the blob. However, the file has 0 bytes.

                string trainingfolder = "Dan"
                string strFilename = Path.GetFileName(hpf.FileName);
                string strFile = Path.GetFileNameWithoutExtension(hpf.FileName);
                string strFileExt =  Path.GetExtension(hpf.FileName);
                System.Drawing.Image image = System.Drawing.Image.FromStream(hpf.InputStream);
                System.Drawing.Image thumbnailImage = image.GetThumbnailImage(100, 100, null, IntPtr.Zero);
                MemoryStream imageStream = new MemoryStream();
                thumbnailImage.Save(imageStream, System.Drawing.Imaging.ImageFormat.Jpeg);
                string NewImageName = strFile + "_thumb" + strFileExt;  
                if (imageStream.Length > 0)
                {
                    CloudStorageAccount storageAccount1 = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
                    CloudBlobClient blobClient1 = storageAccount1.CreateCloudBlobClient();
                    CloudBlobContainer container1 = blobClient1.GetContainerReference(trainingfolder);
                    CloudBlockBlob blockBlob1 = container1.GetBlockBlobReference(NewImageName);
                    blockBlob1.UploadFromStream(imageStream);
                }

Open in new window

OK after working with the code further. I got it to create an image image that has data. However, it does not display. When I download it, I get an error saying invalid Bitmap.

                byte[] originalImage;
                string imageUrl = "https://abc123.com/12.jpg";
                originalImage = new System.Net.WebClient().DownloadData(imageUrl);
                System.IO.MemoryStream imageStream = new System.IO.MemoryStream(originalImage);
                System.Drawing.Image img = System.Drawing.Image.FromStream(imageStream);
                System.Drawing.Image thumbnailImage = img.GetThumbnailImage(100, 100, () => false, IntPtr.Zero);
                thumbnailImage.Save(imageStream, System.Drawing.Imaging.ImageFormat.Jpeg);
                string NewImageName = strFile + "_thumb" + strFileExt;
                if (imageStream.Length > 0)
                {
                    CloudStorageAccount storageAccount2 = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
                    CloudBlobClient blobClient2 = storageAccount2.CreateCloudBlobClient();
                    CloudBlobContainer container2 = blobClient2.GetContainerReference(trainingfolder);
                    CloudBlockBlob blockBlob2 = container2.GetBlockBlobReference(NewImageName);

                    blockBlob2.Properties.ContentType = "image/jpeg";
                    blockBlob2.UploadFromStream(imageStream);
                }

Open in new window

I wanted to add. The original image that was upload is fine. I can display it.
ASKER CERTIFIED SOLUTION
Avatar of RecipeDan
RecipeDan

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I figured it out and it is the best solution.