简体   繁体   中英

Asp.Net Mvc Delete file issue

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

在此处输入图片说明

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.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM