Solved

Create a Thumbnail from image after upload

Posted on 2014-12-12
11
99 Views
Last Modified: 2014-12-20
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

0
Comment
Question by:RecipeDan
  • 7
  • 3
11 Comments
 
LVL 11

Expert Comment

by:LordWabbit
Comment Utility
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.
0
 
LVL 11

Expert Comment

by:LordWabbit
Comment Utility
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.
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
0
 
LVL 1

Author Comment

by:RecipeDan
Comment Utility
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

0
 
LVL 11

Expert Comment

by:LordWabbit
Comment Utility
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.
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 1

Author Comment

by:RecipeDan
Comment Utility
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.
0
 
LVL 1

Author Comment

by:RecipeDan
Comment Utility
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

0
 
LVL 1

Author Comment

by:RecipeDan
Comment Utility
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

0
 
LVL 1

Author Comment

by:RecipeDan
Comment Utility
I wanted to add. The original image that was upload is fine. I can display it.
0
 
LVL 1

Accepted Solution

by:
RecipeDan earned 0 total points
Comment Utility
OK. I figured it out. Just add imageStream.Position = 0; before upload.                

              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);
imageStream.Position = 0;                 
   blockBlob1.UploadFromStream(imageStream);
                }

Open in new window

0
 
LVL 1

Author Closing Comment

by:RecipeDan
Comment Utility
I figured it out and it is the best solution.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
More often than not, we developers are confronted with a need: a need to make some kind of magic happen via code. Whether it is for a client, for the boss, or for our own personal projects, the need must be satisfied. Most of the time, the Framework…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now