0

I have an issue with Files.

I am doing an image importer so clients put their files on an FTP server and then they can import it in the application.

During the import process I copy the file in the FTP Folder to another folder with File.copy

public List<Visuel> ImportVisuel(int galerieId, string[] images)
    {

        Galerie targetGalerie = MemoryCache.GetGaleriById(galerieId);
        List<FormatImage> listeFormats = MemoryCache.FormatImageToList();
        int i = 0;

        List<Visuel> visuelAddList = new List<Visuel>();
        List<Visuel> visuelUpdateList = new List<Visuel>();
        List<Visuel> returnList = new List<Visuel>();
        foreach (string item in images)
        {
            i++;
            Progress.ImportProgress[Progress.Guid] = "Image " + i + " sur " + images.Count() + " importées";
            string extension = Path.GetExtension(item);
            string fileName = Path.GetFileName(item);
            string originalPath = HttpContext.Current.Request.PhysicalApplicationPath + "Uploads\\";
            string destinationPath = HttpContext.Current.Server.MapPath("~/Images/Catalogue") + "\\";
            Visuel importImage = MemoryCache.GetVisuelByFilName(fileName);
            bool update = true;
            if (importImage == null) { importImage = new Visuel(); update = false; }

            Size imageSize = importImage.GetJpegImageSize(originalPath + fileName);
            FormatImage format = listeFormats.Where(f => f.width == imageSize.Width && f.height == imageSize.Height).FirstOrDefault();
            string saveFileName = Guid.NewGuid() + extension;


            File.Copy(originalPath + fileName, destinationPath + saveFileName);


            if (format != null)
            {
                importImage.format = format;
                switch (format.key)
                {
                    case "Catalogue":
                        importImage.fileName = saveFileName;
                        importImage.originalFileName = fileName;
                        importImage.dossier = targetGalerie;
                        importImage.dossier_id = targetGalerie.id;
                        importImage.filePath = "Images/Catalogue/";
                        importImage.largeur = imageSize.Width;
                        importImage.hauteur = imageSize.Height;
                        importImage.isRoot = true;
                        if (update == false) { MemoryCache.Add(ref importImage); returnList.Add(importImage); }
                        if (update == true) visuelUpdateList.Add(importImage);
                        foreach (FormatImage f in listeFormats)
                        {
                            if (f.key.StartsWith("Catalogue_"))
                            {
                                string[] keys = f.key.Split('_');
                                string destinationFileName = saveFileName.Insert(saveFileName.IndexOf('.'), "-" + keys[1].ToString());
                                string destinationFileNameDeclinaison = destinationPath + destinationFileName;
                                VisuelResizer declinaison = new VisuelResizer();
                                declinaison.Save(originalPath + fileName, f.width, f.height, 1000, destinationFileNameDeclinaison);

                                Visuel visuel = MemoryCache.GetVisuelByFilName(fileName.Insert(fileName.IndexOf('.'), "-" + keys[1].ToString()));
                                update = true;
                                if (visuel == null) { visuel = new Visuel(); update = false; }

                                visuel.parent = importImage;

                                visuel.filePath = "Images/Catalogue/";
                                visuel.fileName = destinationFileName;
                                visuel.originalFileName = string.Empty;
                                visuel.format = f;
                                //visuel.dossier = targetGalerie; On s'en fout pour les déclinaisons
                                visuel.largeur = f.width;
                                visuel.hauteur = f.height;
                                if (update == false)
                                {
                                    visuelAddList.Add(visuel);
                                }
                                else
                                {
                                    visuelUpdateList.Add(visuel);
                                }
                                //importImage.declinaisons.Add(visuel);
                            }
                        }
                        break;
                }
            }

        }
        MemoryCache.Add(ref visuelAddList);

        // FONCTION à implémenter
        MemoryCache.Update(ref visuelUpdateList);
        return returnList;
    }

After some processes on the copy (the original file is no more used) the client have a pop-up asking him if he wants to delete the original files in the ftp folder.

If he clicks on Ok another method is called on the same controller and this method use

public void DeleteImageFile(string[] files)
    {
        for (int i = 0; i < files.Length; i++)
        {
            File.Delete(HttpContext.Current.Request.PhysicalApplicationPath + files[i].Replace(@"/", @"\"));
        }
    }

This method works fine and really delete the good files when I use it in other context.

But here I have an error message:

Process can't acces to file ... because it's used by another process.

Someone have an idea?

Thank you.

Here's the screenshot of Process Explorer

enter image description here

6
  • when do you get this error ? after deleting the file? Commented Apr 26, 2017 at 17:07
  • When I want to delete it the error occurs when I call the delete command Commented Apr 26, 2017 at 17:09
  • Did you close the File correctly beforehand? Commented Apr 26, 2017 at 17:19
  • How do you do that? I didn't see something like a Close method in the File class Commented Apr 26, 2017 at 18:24
  • you have to kill the process that is handling the file before you delete it, the easy way is to keep trying to delete it using thread.sleep or mark files to be deleted in a DB table and delete them at a later time Commented Apr 26, 2017 at 19:59

3 Answers 3

1

There are couple of thing you can do here.

1) If you can repro it, you can use Process Explorer at that moment and see which process is locking the file and if the process is ur process then making sure that you close the file handle after your work is done.

2) Use try/catch around the delete statement and retry after few seconds to see if the file handle was released.

3) If you can do it offline you can put in some queue and do the deletion on it later on.

Sign up to request clarification or add additional context in comments.

8 Comments

I can't do it offline. It's a web app. try catch doesn't work either. the catch is called in loop. How do you clos the file handle? I use the File class and I didn"t see anything for that. Thanks
When you get exception, add that in an array , and then retry after sometime.
@Julien can you show the code. That will make it much easier to help.
I added the two full methods in the question. These two methods are in a disposable class called in a using statement from a controller. So the class is disposed between the two method calls
@Julien you got to find which process is holding the file handle using Process Explorer.
|
0

You solve this by using c# locks. Just embed your code inside a lock statement and your threads will be safe and wait each other to complete processing.

Comments

0

I found the solution:

in my import method, there a call to that method

public void Save(string originalFile, int maxWidth, int maxHeight, int quality, string filePath)
        {
            Bitmap image = new Bitmap(originalFile);
            Save(ref image, maxWidth, maxHeight, quality, filePath);
        }

The bitmap maintains the file opened blocking delete.

just added

image.Dispose();

in the methos and it work fine.

Thank you for your help, and thank you for process explorer. Very useful tool

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.