Link to home
Start Free TrialLog in
Avatar of adampirata
adampirata

asked on

IIS Locks File and refuses to allow delete!?!?

Ok, I need some help here, I have googled this to death and found no solution that works.
Here i smy scenario:

ASP.NET form upload a image, image is possibly resized and saved to /Images/Temp folder.

At this point, the image might need to be cropped, and if so I send the user back to a page which displays the image. The user specifies what area they want to crop and hits continue.

The problem is that since IIS has now served up this image to a web browser, it is now locked by IIS. If I do utterly nothing except File.Delete(PathToFile) I will still get an access denied error saying the file is in use.

People are uploading 3MB files to resize/crop and I need the ability to delete them out of this Temp folder after the smaller cropped image is saved.

The only way I can delete the file now is to wait about 20 minutes (I guess the session is timing out?) or restart the app pool for the website. Both are not acceptable solutions.

I tried disabling output caching in IIS 7.5 for my temp folder, and it created a web.config file in the Temp folder that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <caching>
            <profiles>
                <add extension=".jpg" policy="DontCache" kernelCachePolicy="DontCache" />
            </profiles>
        </caching>
    </system.webServer>
</configuration>


However, I STILL can't delete the file. I have to show it to the user (so they not what to crop) and then I want it GONE out of the /Images/Temp folder.

How can I get IIS to let go of the file so I can delete it?

Any help would be appreciated.
Avatar of jijeesh
jijeesh
Flag of India image

Can you check whther the files are closed after processing it.
Avatar of Nirmalan Nagenthiran
Try some thing once you write the file to the browser

 //Write the File to browser
 Response.WriteFile(file.FullName);
 Response.Flush();
 Response.End();
Avatar of adampirata
adampirata

ASKER

NNirmalan, there is no place for me to put that code, I am not "wrting" the file to Response, I am simply calling it in a IMG tag.

Let me throw in some more details to see if that helps.

Steps to reproduce:
1) File is uploaded via asp:FileUpload.
2) File is saved. If I wanted to delete it here with File.Delete(FileName) it works just fine. This isn't where I want it delete though.
3) Next this:
ImageToCrop.ImageUrl =  "/Images/Temp/" + sFileName;
mvMain.SetActiveView(vEditImage);

All this does is present the user the image in a browser. At this point I am now screwed for deleting the file.
4) I put a button under the image and on the click event, I tried deleting the file. At this point it is now locked by IIS because IIS served up the file.

I already tried making the ImageURL dynamic like GetImage.aspx?Path=/Images/Temp, figuring I could control the opening and closing of the file....the file cropping DLL I am using WebCropImage.UI won't work with a dynamic URL.

I have definately pinpointed that setting this: ImageToCrop.ImageUrl =  "/Images/Temp/" + sFileName; and then navigating to that page is what is locking the file.

Hmm, you must have something else going on...the code below works as expected for me on both IIS 7 and IIS 6.
Are you disposing of any objects from WebCrop.UI that might have opened the file, and does your web application have the necessary NTFS permissions to delete files?

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
	private void UploadButton_Click(object sender, EventArgs e)
	{
		if (ImageUploader.HasFile)
		{
			string imageUrl = "~/Temp/" + System.IO.Path.GetRandomFileName() + ".jpg";
			ImageUploader.SaveAs(Server.MapPath(imageUrl));
			ImageToCrop.ImageUrl = imageUrl;
		}
	}

	private void DeleteImageButton_Click(object sender, EventArgs e)
	{
		System.IO.File.Delete(Server.MapPath(ImageToCrop.ImageUrl));
		ImageToCrop.ImageUrl = String.Empty;
	}
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <asp:FileUpload id="ImageUploader" runat="server" /><br />
	<asp:Button ID="UploadButton" runat="server" Text="Upload Image" OnClick="UploadButton_Click" />
	<br />
	<asp:Button ID="DeleteImageButton" runat="server" Text="Delete Image" OnClick="DeleteImageButton_Click" />
	<br />
	<asp:Image id="ImageToCrop" runat="server" />
    </div>
    </form>
</body>
</html>

Open in new window

...with what are basically default settings in both cases, and a mostly-empty web.config:

<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433 
-->
<configuration>
<connectionStrings>
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0">
</compilation>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/></system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
</modules>
</system.webServer>
</configuration>
@tgerbert

I will try your code and see if that works on my server.  I did actually give full control to EVERYONE for that temp folder and subdirectories, so it shouldn't be a permission issue. I know that isn't a solution in the long term, but it should rule out permisssions "for now".

Let me try your code and see if I can identify some differences to narrow down my issue.

Thank you.
I've been monkying around a little bit with the WebCrop control - it seems this has locked the file, so you will need to either 1) find an alternate control that does the same thing (without leaving the file locked), 2) modify the source code for this control so you can make sure it's releasing resources (I already tried calling .Dispose() on the WebCrop object with no success), or 3) Live with a bunch of temp files on the server and clear'em out periodically.
(Actually, calling WebCrop.Dispose() followed by GC.Collect() works - but you don't want to be calling GC.Collect in a production web app, though it does indicate the WebCrop control might have an empty Dispose() implementation)
ASKER CERTIFIED SOLUTION
Avatar of Todd Gerbert
Todd Gerbert
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you so much for your help. It never occured to me that the WebCrop tool would lock the file when I wasn't actually doing a crop with it. Apparently it had to get the file dimensions just to render on the screen...and as you found out, they didn't release the file.

All is working now...you saved me hours of frustration, thank you!