Tech Off Thread

6 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

Problem with files

Back to Forum: Tech Off
  • User profile image
    arjasepp

    I made this little webapp, that uploads a file, prefered picture file.
    I save this picture and try to resize it or get a thumbnail out of it.
    Before I save picture I want to clear the folder that contains that picture and thumbnail. The first time I upload a file, everything is ok, but the second time I try to do it, I get an IO error, that the file is in use.
    I add some code in here:

    //Main click method
    if (fuFail.HasFile)
            {
                HttpPostedFile postedFile = fuFail.PostedFile;
                string failiNimi = fuFail.FileName;
                deleteFiles();
                string originalPicLocation = Server.MapPath("") + @"\pildid\" + failiNimi;
                string thumbnailLocation = Server.MapPath("") + @"\pildid\thumb_" + failiNimi;
                if (postedFile.ContentType.Contains("image"))
                {
                    saveFileFromStream(postedFile, originalPicLocation);

                    Image img = Image.FromFile(originalPicLocation);
                    //Picture information
                    int kõrgus = img.Height;
                    int laius = img.Width;
                    //size calculations method here
                    Image.GetThumbnailImageAbort myCallBack = new Image.GetThumbnailImageAbort(ThumbnailCallback);
                    img = img.GetThumbnailImage(laius, kõrgus, myCallBack, IntPtr.Zero);
                    img.Save(thumbnailLocation);
                    img.Dispose();
                    Image1.ImageUrl = "./pildid/thumb_" + failiNimi;
                }
            }

    //the method that causes the error
    private void deleteFiles()
        {
            string[] failid = Directory.GetFiles(Server.MapPath("") + @"\pildid");
            for (int i = 0; i < failid.Length; i++)
            {
                File.Delete(failid[i]);
            }
        }

    //Method that saves the file from stream
    private void saveFileFromStream(HttpPostedFile postedFile, string asukohtSuurelPildil)
        {
            byte[] buffer = new byte[postedFile.InputStream.Length];
            postedFile.InputStream.Read(buffer, 0, Convert.ToInt32(postedFile.InputStream.Length));
            FileStream fs = new FileStream(asukohtSuurelPildil, FileMode.Create);
            fs.Write(buffer, 0, Convert.ToInt32(postedFile.InputStream.Length));
            fs.Flush();
            fs.Close();
            fs.Dispose();
            postedFile.InputStream.Close();
            postedFile.InputStream.Dispose();
        }

    What am I doing wrong or how to solve this issue? ASP.NET 2.0 just holds the file somehow, why? I don't know.

    And the error, that I get is:
    Exception Details: System.IO.IOException: The process cannot access the file 'E:\Files\jaan\pildisuurus\pildid\IMG_9632.JPG' because it is being used by another process.

    Source Error:

    Line 57:         for (int i = 0; i < failid.Length; i++)
    Line 58: {
    Line 59: File.Delete(failid[i]);
    Line 60: }
    Line 61: }

    If you could tell, why the file is beeing kept by the ASP.NET process, I would appreciate it.

  • User profile image
    TommyCarlier

    I think Image.FromFile keeps the file locked. Try to replace this:

    Image img = Image.FromFile(originalPicLocation);
    with this:
    Image img = null;
    using(FileStream fs = new FileStream(originalPicLocation, FileMode.Open, FileAccess.Read))
    {
       img = Image.FromStream(fs);
    }

  • User profile image
    Sven Groot

    That might not work. GDI+ will in some cases defer decoding of the image, so if you dispose the stream before you're done with the image, it might fail. That's also the reason why it keeps the file locked.

    The real problem in Arjasepp's code is that he creates the image, then creates a thumbnail, and then disposes the thumbnail but not the original image. That keeps the file locked even after you're done with the image (until the GC decides to collect the image).

    Change the code to this:
    using( Image img = Image.FromFile(originalPicLocation) )
    {
      int kõrgus = img.Height;
      int laius = img.Width;
      //size calculations method here
      Image.GetThumbnailImageAbort myCallBack = new Image.GetThumbnailImageAbort(ThumbnailCallback);
      using( Image thumbnail = img.GetThumbnailImage(laius, kõrgus, myCallBack, IntPtr.Zero) )
      {
        thumbnail.Save(thumbnailLocation);
      }
    }
    Image1.ImageUrl = "./pildid/thumb_" + failiNimi;

    That will make sure the image is always disposed so the file won't remain locked.

  • User profile image
    arjasepp

    Thanks, first solution worked allright, but I will try the other solution as well.
    Though I had to move most of the code concerning Image object into the scope, otherwise I got Out of memory exception.
    Smiley

  • User profile image
    Sven Groot

    arjasepp wrote:
    Thanks, first solution worked allright, but I will try the other solution as well.
    Though I had to move most of the code concerning Image object into the scope, otherwise I got Out of memory exception.
    Smiley

    That's what I meant, if you do it the way Tommy described the Image class is trying to access the stream after you've disposed it.

    Anyway, even with the FromStream method, it's still a good idea to make sure you Dispose the Image as well.

    EDIT: An OutOfMemoryException is Image's weird way of letting you know something is wrong. Even if the image is corrupt, it'll give you an OutOfMemoryException. That's why I prefer to use "new Bitmap(file)" instead of "Image.FromFile(file)". They do basically the same thing but the Bitmap constructor gives a more sensible ArgumentException when something is wrong with the image.

  • User profile image
    deanme

    I finally gave up on using the GetThumbNailFromImage.

    I am using the following now and it works without error:


    private void ShingImage(string sourceFileName,string destFileName)

    {

       Bitmap image = new Bitmap(sourceFileName);

       System.IO.MemoryStream lmemStream = 
          new System.IO.MemoryStream();

       image.Save(lmemStream, ImageFormat.Jpeg);

       image = new Bitmap(lmemStream);

       const int WIDTH = 80;

       int linHeight = Convert.ToInt32(Math.Round((WIDTH * 
       (Convert.ToDecimal(image.Height) / Convert.ToDecimal
       (image.Width))), 0));

       Bitmap newImage = new Bitmap(WIDTH, linHeight);

       Graphics lobGR = Graphics.FromImage(newImage);

       lobGR.DrawImage(image, 0, 0, WIDTH, linHeight);

       lmemStream = new System.IO.MemoryStream();

       newImage.Save(lmemStream, ImageFormat.Jpeg);

       //if you want to return the stream instead, you can stop here

       using (System.IO.FileStream sw = new 
          System.IO.FileStream   (destFileName, 
          System.IO.FileMode.Create, System.IO.FileAccess.Write, 
          System.IO.FileShare.None, Convert.ToInt32
          (lmemStream.Length)))

       {
       sw.Write(lmemStream.ToArray(), 0, 
       Convert.ToInt32   (lmemStream.Length));

       sw.Close();

    }

    }

     

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.