0

I have a file upload control that allows users to upload an image file. Rather then forcing them to use a specific size image, I am trying to resize it, save it the resized version to a folder and then delete the original.

When I try to delete the file, I keep getting "file in use" exception. I have searched and tried all suggestions to no avail.

This is the latest try, at which point I decided to seek help. I pass the source path (where original file is in, a destination path where resized file is to end up in, file name and width to which it should be resized, keeping aspect ratio):

public static void CreateResizedCopy(String sourcePath, String destinationPath, String filename, int width)
{
    if (!File.Exists(destinationPath + filename))
    {
        System.Drawing.Image image = System.Drawing.Image.FromFile(sourcePath + filename);
        float AspectRatio = (float)image.Size.Width / (float)image.Size.Height;
        int newHeight = Convert.ToInt32(width / AspectRatio);
        Bitmap thumbnailBitmap = new Bitmap(width, newHeight);
        Graphics thumbnailGraph = Graphics.FromImage(thumbnailBitmap);
        thumbnailGraph.CompositingQuality = CompositingQuality.HighQuality;
        thumbnailGraph.SmoothingMode = SmoothingMode.HighQuality;
        thumbnailGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;
        var imageRectangle = new Rectangle(0, 0, width, newHeight);
        thumbnailGraph.DrawImage(image, imageRectangle);
        thumbnailBitmap.Save(destinationPath + filename, ImageFormat.Jpeg);
        thumbnailGraph.Dispose();
        thumbnailBitmap.Dispose();
        image.Dispose();

        System.GC.Collect();
        System.GC.WaitForPendingFinalizers();

        if (!FileInUse(sourcePath + filename))
        {
            File.Delete(sourcePath + filename);
        }
        else
        {
            // Error here: file is in use
            using (FileStream fs = new FileStream(sourcePath + filename, FileMode.OpenOrCreate))
                fs.Dispose();
        }
    }
}

public static bool FileInUse(string path)
{
    try
    {
        using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate))
        {
            return false;
        }
    }
    catch (IOException ex)
    {
        return true;
    }
}

UPDATE This is the AJAX AsynFileUpload's upload completed event handler. It saves the file to a "Resize" folder. If image needs to be resized, it calls the method to resize it and then moves it to its final resting place. If not, no resizing is done, it just moves the file. It then "attempts" to delete the file in resize folder and it chokes!

protected void fuNewsImage_UploadedComplete_Resize(object sender, AsyncFileUploadEventArgs e)
{
    if (fuNewsImage.HasFile)
    {
        HttpPostedFile file = fuNewsImage.PostedFile;
        string sFileName = fuNewsImage.FileName;
        string sFileSize = e.FileSize;

        string sSaveFolder = ImageFilePath.TEMP_FOLDER_EA_TEST + "\\";
        string sResizeFolder = ImageFilePath.TEMP_FOLDER_EA_TEST + "\\Resized\\";

        fuNewsImage.SaveAs(Server.MapPath(sResizeFolder + sFileName));
        System.Drawing.Image img = System.Drawing.Image.FromFile(Server.MapPath(sResizeFolder) + sFileName);
        int iImgWidth = img.Width;
        int iImgHeight = img.Height;

        if (iImgWidth > ImageInfo.MAX_WIDTH)
        {
            // sSaveFolder is the efinal resting place of the uploaded image
            // If image width is more than max allowed, resize it, save it in sSaveFolder
            Utils.CreateResizedCopy(Server.MapPath(sResizeFolder), Server.MapPath(sSaveFolder), sFileName, 600);

            System.Threading.Thread.Sleep(1000);
            File.Delete(Server.MapPath(sSaveFolder + sFileName));
        }
        else  // just move it t sSaveFolder
        {
            File.Move(Server.MapPath(sResizeFolder) + sFileName, Server.MapPath(sSaveFolder) + sFileName);
        }
        //        ---  Chokes here  ---
        Array.ForEach(Directory.GetFiles(Server.MapPath(sResizeFolder)), File.Delete);
    }
}
NoBullMan
  • 2,032
  • 5
  • 40
  • 93
  • And the code that saves the file closes everything properly? – Sami Kuhmonen Jul 30 '17 at 20:43
  • Are you sure you don't have any other open handles to the file in code outside of these two methods? I just ran your code against a test image in LINQPad and it deleted the source file successfully. – Connor Jul 30 '17 at 20:47
  • 1
    You should rarely ever need to call `.Dispose()` directly in your methods. You should be wrapping each of the disposable objects with a `using` statement instead. – Scott Chamberlain Jul 30 '17 at 20:48
  • 1
    I also tried this in a new c# console project and it works fine. However, I suggest you create paths using Path.Combine(sourcePath, filename) instead of using sourcePath + filename everywhere. –  Jul 30 '17 at 20:53
  • 1
    Try this, don't use `Image.FromFile`, read all the data in memory, create a MemoryStream and construct the image from there, then check if you can delete the file. If no, then post the download code as you may have left the file open somewhere else. – Gusman Jul 30 '17 at 21:37
  • I updated the post with the code that handles file upload's UploadCompleted event handler. Also, thank you for hint on using Path.Combine(); I will update my code to use it. – NoBullMan Jul 31 '17 at 14:10
  • If you want to delete the file right after you upload it, why save it in the first place? Your code isn't the only thing that opens files, especially in IIS. Don't save it until you need it persisted. – Luaan Jul 31 '17 at 14:21
  • How do I get the width/height of the image to check if it is within acceptable range if I haven't saved it as a file? If it is not within range, how would I pass the source path to resize method to resize it? – NoBullMan Jul 31 '17 at 14:46

0 Answers0