0

I'm having a big headache with the following:

private bool AddImageToUser(HttpPostedFileBase photo)
{
    string userId = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).UserData.Split('|')[0];
        string newPath = "", path = "";
        string userDir = System.Web.HttpContext.Current.Server.MapPath(vars.getKeyValue("usersImagesPath") + "/" + userId);
        System.IO.Directory.CreateDirectory(userDir);//create directory if it doesn't exist
        bool valid = false;
        try
        {
            path = Directory.GetFiles(userDir, "*foto_perfil.*").First();

                if (path.Length > 0 && path != null)
                {
                    string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
                    newPath = path.Replace(fileNameWithoutExtension, fileNameWithoutExtension + "_old");

                    System.IO.File.Move(path, newPath);
//The exception i'm refering to, happens with this File.Move
                    }
            }
            catch { }
        //add a new image and replace the old one
        try
        {
            HttpPostedFileBase attFile = photo;
            int attachFileLength = attFile.ContentLength;
            if (attachFileLength > 0)
            {
                string _name = attFile.FileName;
                _name = _name.Substring(_name.LastIndexOf('\\') + 1);
                string nome_ficheiro = DateTime.Now.ToString("ddMMyyyyhhmmfff") + "foto_perfil." + Path.GetExtension(attFile.FileName).Substring(1).ToLower();
                attFile.SaveAs(System.Web.HttpContext.Current.Server.MapPath(vars.getKeyValue("usersImagesPath") + "/" + userId + "/" + nome_ficheiro)); //falta fazer o upload do ficheiro

                if (newPath != "")
                    System.IO.File.Delete(newPath);
                valid = true;
            }
        }
        catch
        {
            //If there is an error saving new image, put the old one back if it exists
            System.IO.File.Move(path, newPath);
            valid = false;
        }
        return valid;
    }

What i'm trying there is, discover the full path, to the only image file that is on a directory, and then in the variable "newPath" i get the that same path but with a rename. But when i get to File.Move, wich the intention is to rename the file using the "newPath" i get most of the times the error:

The process cannot access the file ... because it is being used by another process

StackTrace

StackTrace  "   em System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)\r\n   em System.IO.__Error.WinIOError()\r\n   em System.IO.File.InternalMove(String sourceFileName, String destFileName, Boolean checkHost)\r\n   em System.IO.File.Move(String sourceFileName, String destFileName)\r\n   em PGR_01.Controllers.AccountController.AddImageToUser(HttpPostedFileBase photo) em c:\\Dev\\Websites\\MVC\\PGR_01\\PGR_01\\Controllers\\AccountController.cs:line 409"   string

Btw, in the same Razor page that i use to upload the new image, i'm displaying the last image upload, getting the path with a custom attribute:

In the page:

<img class="col-md-6 col-md-offset-3" src="/util/imgLoader2.ashx?h=214&amp;w=320&amp;img=@Html.pathOfUserPhoto()"/>

code:

public static MvcHtmlString pathOfUserPhoto(this HtmlHelper htmlHelper)
{
    string userId = FormsAuthentication.Decrypt(HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName].Value).UserData.Split('|')[0];

    string htmlString, userDir = System.Web.HttpContext.Current.Server.MapPath(vars.getKeyValue("usersImagesPath") + "/" + userId);
    //using
    //{
    try
    {
        htmlString = Directory.GetFiles(userDir, "*foto_perfil.*").First();
    }
    catch
    {
        htmlString = "";
    }
    return new MvcHtmlString(htmlString);
    //return MvcHtmlString.Empty;
}

I don't think it has anything to do with it.

What am i doing wrong? Is there a better way to do this?

Note: this error never happens if the folder is empty. Note 2: If i try to delete the file manually after being upload sometimes i can't because it says it's already being used by "IIS Express Worker Process"

EDIT:

I've found what is causing the lock, it's the following IHttpHandler that i call in the source of the img element. Is there something i can do to prevent it from locking the image?

public class imgLoader2 : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {

        int Width = 0;
        int Height = 0;
        string imgFile = vars.serverFolder;
        string imgName = context.Request.QueryString["img"];
        //string def = "/upload/blank.jpg";
        string def = "/Uploads/blank.jpg";

        System.Drawing.Image imgPhoto = null;

        ImageFormat format = ImageFormat.Jpeg;
        context.Request.ContentType = "image/jpeg";
        ImageResize imgUtil = new ImageResize();
      //  HttpContext.Current.Response.Cache.SetExpires(yourCalculatedDateTime);
        context.Response.Cache.SetCacheability(HttpCacheability.Public);
        context.Response.Cache.SetExpires(DateTime.Now.AddDays(8));
        context.Response.Cache.SetLastModified(DateTime.Now);
        if(string.IsNullOrEmpty(imgName))
            imgName=def;

        if (context.Request.QueryString.Count > 0)
        {
            if (context.Request.QueryString["h"] != null)
                Height = Convert.ToInt16(context.Request.QueryString["h"]);

            if (context.Request.QueryString["w"] != null)
                Width = Convert.ToInt16(context.Request.QueryString["w"]);

            if (!string.IsNullOrEmpty(imgName))
            {
                imgPhoto = imgUtil.imgThumbCropTop(imgFile + imgName, Width, Height);
            }
            else
            {
                imgPhoto = imgUtil.imgThumbCropTop(context.Server.MapPath("~/" + def), Width, Height);

            }
            //imgPhoto = imgUtil.imgThumb(imgFile + imgName, Height);
        }
        else
        {
            imgPhoto = imgUtil.imgThumbCropTop(context.Server.MapPath("~/" + def), Width, Height);
        }

        if (imgName.ToLower().EndsWith(".gif"))
        {
            format = ImageFormat.Gif;
            context.Response.ContentType = "image/gif";
        }
        else if (imgName.ToLower().EndsWith(".png"))
        {
            format = ImageFormat.Png;
            context.Response.ContentType = "image/png";
        }
        else
        {
            format = ImageFormat.Jpeg;
            context.Response.ContentType = "image/jpeg";
        }

        try
        {
            imgPhoto.Save(context.Response.OutputStream, format);
        }
        catch
        {
            //context.Request.ContentType = "image/gif";
            imgPhoto = imgUtil.imgThumbCrop(context.Server.MapPath("~/" + def), Width, Height);
            imgPhoto.Save(context.Response.OutputStream, format);
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}
Nmaster88
  • 1,405
  • 2
  • 23
  • 65
  • Did you check in task manager if the file is open in background by a program ? – Coskun Ozogul May 03 '17 at 09:32
  • Your exception is self explanatory, try finding the process which puts your file on lock. – M. Adeel Khalid May 03 '17 at 09:47
  • 2
    Was this an uploaded file? Did you *close* its stream after receiving it? Did you try to move a file that was being uploaded? What generates these files? – Panagiotis Kanavos May 03 '17 at 09:47
  • 1
    @Nmaster88 The problem is not related to `Directory.GetFiles` somewhere something, probably in your code, is locking that file. – TheLethalCoder May 03 '17 at 10:14
  • @TheLethalCoder I'm having a lot of difficulties finding what can be locking the file, do you suggest another way of doing that code? – Nmaster88 May 03 '17 at 10:33
  • Do you identify this issue while debugging or at runtime? The first File.Move is within an empty catch block, so any exception will be swallowed, but there is another File.Move below within your last catch block that will bubble up the exception. Can you confirm which File.Move is causing this exception? – Thangadurai May 03 '17 at 11:59
  • @Thangadurai it's the first. I think i've found now whats locking the image. It's an IHTTphandler i call from src of the img element in the site. – Nmaster88 May 03 '17 at 12:02
  • There are few workarounds mentioned [here](http://stackoverflow.com/questions/876473/is-there-a-way-to-check-if-a-file-is-in-use). You can try using this in your HttpHandler. – Thangadurai May 03 '17 at 12:07

1 Answers1

0

It seems that my HttpHandler was calling a method that had an Image.FromFile that was locking the file!

            if (!imgFile.Contains("://i.ytimg.com/"))
                //using(Image img = Image.FromFile(imgFile))
                  //  imgPhotoHoriz = img;
                imgPhotoHoriz = Image.FromFile(imgFile);
            else

I changed it to this

            using(FileStream stream = new FileStream(imgFile,FileMode.Open,FileAccess.Read)){
            if (!imgFile.Contains("://i.ytimg.com/"))
                //imgPhotoHoriz = Image.FromFile(imgFile);
                imgPhotoHoriz = Image.FromStream(stream);
            else

I'm going to remember this from now on. Hope it helps more people!

Nmaster88
  • 1,405
  • 2
  • 23
  • 65