ASP.NET-使用System.IO.File.Delete()从wwwroot目录内删除文件?

3

我有一个ASP.NET SOAP Web服务,它的Web方法创建一个PDF文件,将其写入应用程序的“下载”目录,并将URL返回给用户。 代码:

//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();
}

然后在Web服务的Global.asax文件中,我在Application_Start事件监听器中设置了一个定时器。在定时器的ElapsedEvent监听器中,我查找下载目录中任何早于定时器间隔(测试为1分钟,部署约20分钟)的文件并将其删除。 代码:

//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);
        }
    }
}

这个功能完美地运行,只有一个例外。当我将 Web 服务应用程序发布到 inetpub\wwwroot(Windows 7,IIS7)时,它不会删除 Download 目录中的旧文件。当我从不在 wwwroot 中的物理目录发布到 IIS 时,该应用程序运行得很完美。显然,IIS 对 web 根目录中的文件施加了某种锁定。我已经测试过模拟管理员用户运行应用程序,但仍然无法正常工作。有没有什么方法可以在编程时规避 wwwroot 中的锁定?客户可能希望将应用程序发布到根目录。

它是默默失败还是抛出异常?如果是异常,请发布堆栈跟踪(当然,根据需要进行安全修整!)。 - Jeff Sternal
你是否有类似“每次启动只删除一个文件”的功能? - Seb
@ Jeff - 就我看来,它在默默地失败。由于它位于global.asax中,我不确定它会在哪里引发错误(或者File.Delete()是否会为此引发错误)。计算机管理中的事件查看器似乎没有列出任何适用的事件。@ Seb - 我想我不确定你的意思是什么,但是当在wwwroot之外正常工作时,所有“旧”文件都将被删除。 - Jim S
3个回答

4

您的问题可能与IIS重新加载Web服务应用程序有关,如果主文件夹中包含的目录或文件发生更改。

尝试在应用程序根文件夹之外创建/删除文件的临时文件夹(注意文件夹权限以允许IIS读写文件)。


@T.Falise 感觉我们在思考同样的问题;-) - Seb
当应用程序结束并重新启动(在文件更改、非使用等情况下)时,当Web服务应用程序位于wwwroot之外时,它可以正常工作。下载目录(物理和虚拟)位于应用程序根目录内部,当应用程序不在wwwroot内部时,它可以正常工作。我需要将所有物理目录保留在应用程序目录内。谢谢。 - Jim S

1

0

我忘记回来回答我的问题了。

我不得不给 IIS_IUSRS 组在我读写文件的目录中赋予 修改 权限。

感谢所有回答我的人。


你有没有注意到Thibault Falise在他的回答中提到了这一点?从技术上讲,应该算是他的回答,至少我是这么认为的。 - Srikanth Venugopalan
我不同意,Srikanth。虽然我非常感谢Thibault的帮助,它确实有所帮助,但我知道权限很可能是罪魁祸首。那个答案是针对应用程序重新加载期间文件结构可能发生变化的可能性而言的。我的回答解决了特定问题的解决方案。 - Jim S

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接