I have a ASP.NET SOAP web service whose web method creates a PDF file, writes it to the "Download" directory of the applicaton, and returns the URL to the user. Code:
//Create the map images (MapPrinter) and insert them on the PDF (PagePrinter).
MemoryStream mstream = null;
FileStream fs = null;
try
{
//Create the memorystream storing the pdf created.
mstream = pgPrinter.GenerateMapImage();
//Convert the memorystream to an array of bytes.
byte[] byteArray = mstream.ToArray();
//return byteArray;
//Save PDF file to site's Download folder with a unique name.
System.Text.StringBuilder sb = new System.Text.StringBuilder(Global.PhysicalDownloadPath);
sb.Append("\\");
string fileName = Guid.NewGuid().ToString() + ".pdf";
sb.Append(fileName);
string filePath = sb.ToString();
fs = new FileStream(filePath, FileMode.CreateNew);
fs.Write(byteArray, 0, byteArray.Length);
string requestURI = this.Context.Request.Url.AbsoluteUri;
string virtPath = requestURI.Remove(requestURI.IndexOf("Service.asmx")) + "Download/" + fileName;
return virtPath;
}
catch (Exception ex)
{
throw new Exception("An error has occurred creating the map pdf.", ex);
}
finally
{
if (mstream != null) mstream.Close();
if (fs != null) fs.Close();
//Clean up resources
if (pgPrinter != null) pgPrinter.Dispose();
}
Then in the Global.asax file of the web service, I set up a Timer in the Application_Start event listener. In the Timer's ElapsedEvent listener I look for any files in the Download directory that are older than the Timer interval (for testing = 1 min., for deployment ~20 min.) and delete them. Code:
//Interval to check for old files (milliseconds), also set to delete files older than now minus this interval.
private static double deleteTimeInterval;
private static System.Timers.Timer timer;
//Physical path to Download folder. Everything in this folder will be checked for deletion.
public static string PhysicalDownloadPath;
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
deleteTimeInterval = Convert.ToDouble(System.Configuration.ConfigurationManager.AppSettings["FileDeleteInterval"]);
//Create timer with interval (milliseconds) whose elapse event will trigger the delete of old files
//in the Download directory.
timer = new System.Timers.Timer(deleteTimeInterval);
timer.Enabled = true;
timer.AutoReset = true;
timer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimedEvent);
PhysicalDownloadPath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + "Download";
}
private static void OnTimedEvent(object source, System.Timers.ElapsedEventArgs e)
{
//Delete the files older than the time interval in the Download folder.
var folder = new System.IO.DirectoryInfo(PhysicalDownloadPath);
System.IO.FileInfo[] files = folder.GetFiles();
foreach (var file in files)
{
if (file.CreationTime < DateTime.Now.AddMilliseconds(-deleteTimeInterval))
{
string path = PhysicalDownloadPath + "\\" + file.Name;
System.IO.File.Delete(path);
}
}
}
This works perfectly, with one exception. When I publish the web service application to inetpub\wwwroot (Windows 7, IIS7) it does not delete the old files in the Download directory. The app works perfect when I publish to IIS from a physical directory not in wwwroot. Obviously, it seems IIS places some sort of lock on files in the web root. I have tested impersonating an admin user to run the app and it still does not work. Any tips on how to circumvent the lock programmatically when in wwwroot? The client will probably want the app published to the root directory.