2012-02-21 39 views
1

问题:如何覆盖/更新当前由IIS提供的文件?

我的公司推出了我在我们内部网站上托管的每月通讯。我有一个通讯作者的页面上传最新版本。一旦作者上传了最新的时事通讯,他就会发送广播电子邮件来宣布新的时事通讯。员工总是检查新的时事通讯并向作者发送反馈,并进行更正。

一旦作者做出必要的修正(通常发送广播电子邮件的一个小时内),他再次访问我的网页,并替换最新版本与更新的通讯。

紧随更换(或更新,如果你愿意)的通讯的,任何人试图访问它得到500 - 内部服务器错误。

维护服务器的IT人员由于权限错误无法删除/重命名/移动文件,因此必须执行许多令人费解的操作来删除文件(并且一旦文件被删除,作者通讯可以重新上传正确的副本,它的工作正常。

我的IT人员和我很确信,问题源于我试图替换文件,而IIS正在积极为用户提供服务(我想到并认为我已经编码发生了)

运行替换的代码如下:

Protected Sub ReplaceLatestNewsletter() 
    Dim dr As DataRow 
    Dim sFile As String 
    Dim mFileLock As Mutex 

    Try 
     If Me.Archives.Rows.Count > 0 Then 
      dr = Me.Archives.Rows(0) 
      sFile = dr("File").ToString 

      If dr("Path").ToString.Length > 0 Then 
       mFileLock = New Mutex(True, "MyMutexToPreventReadsOnOverwrite") 

       Try 
        mFileLock.WaitOne() 
        System.IO.File.Delete(dr("Path").ToString) 
       Catch ex As Exception 
        lblErrs.Text = ex.ToString 
       Finally 
        mFileLock.ReleaseMutex() 
       End Try 
      End If 

      fuNewsletter.PostedFile.SaveAs(Server.MapPath("~/Newsletter/archives/" & sFile)) 
     End If 
    Catch ex As Exception 
     lblErrs.Text = ex.ToString 
    End Try 

    dr = Nothing 
    sFile = Nothing 
    mFileLock = Nothing 
End Sub 

我以为Mutex会照顾这个(虽然经过重新阅读文档,我不知道我实际上可以使用它像我想)。上面的代码其他评论:

  • Me.Archives是存储在ViewState
  • dr("File").ToString一个DataTable是文件名(无路径)
  • dr("Path").ToString是完整的本地机器路径和文件名(即,C:\ APP_ROOT \通讯\档案\ 20120214.pdf')
  • 的通讯的文件名设置为‘YYYYMMDD.pdf’其中YYYYMMDD是上传的日期(格式)。

在任何情况下,我敢肯定,上面的代码是不建立文件上的独占锁,以使文件可以被安全地覆盖。

最后,我想,以确保发生以下情况:

  1. 如果IIS现任文件,等到IIS完成服务它。
  2. 之前IIS可以再次提供服务的文件,该文件确立的排他锁,这样其他进程,线程,用户(等)无法读取或写入文件。
  3. 删除该文件完全谱写新的文件来替换它或覆盖与新内容的现有文件。
  4. 删除独占锁以便用户可以再次访问文件。

建议?

此外,我可以使用Mutex获取Windows文件系统中文件的互斥锁吗?

预先感谢您为您的帮助和建议。

编辑:

,对于产生的通讯链路是基于物理文件名的方式。使用的方法是:

  1. 获取“存档”目录中的所有PDF文件。对于每个文件:
  2. 解析公布的从文件名的日期。
  3. 店日期,文件路径,文件名,并在DataTable
  4. 排序DataTable按日期(降序)的URL的每个文件在DataRow
  5. 输出第一行作为当前问题。
  6. 输出所有后续行作为“档案”按年份和月份举办。

UPDATE

代替不能够在该文件中的所有现有请求已经完成辨别的,我接过仔细看看@贾斯汀的回答(“你的互斥的第一部分将只有在从文件中读取的进程也获得相同的互斥量时才有效果。“)

这导致我在Configure IIS7 to server static content through ASP.NET Runtime和被接受的答案中链接的文章。

为此,我对所有实现New Mutex(True, "MyMutexToPreventReadsOnOverwrite")的PDF文件实施了一个处理程序,以确保在任何给定时间只有一个线程正在使用PDF进行操作。

谢谢你的回答,@Justin。虽然我没有结束使用您建议的实现,但您的回答指向我一个可接受的解决方案。

+0

我添加了c#标签,因为我可以读取c#并将其翻译回vb.net。随意在c#中发布代码。 – pete 2012-02-21 16:37:04

+0

所有应有的尊重 - 这是愚蠢的。为什么不只是1)上传到“暂存区域”(即*始终*可写入),然后2)复制 - 在“正在使用文件”错误时“重试”? – paulsm4 2012-02-21 16:48:15

回答

3

你互斥才会有效果,如果从文件读取过程中也得到相同的互斥。用于提供文件的方法是什么?是使用ASP.Net还是只是一个静态文件?

我的工作流程将是一个有点不同:

  1. 写入新的通讯到文件
  2. 有IIS开始提供了新的文件,而不是旧的给定的通讯地址
  3. 删除旧文件,一旦该文件的所有现有请求已经完成

这不需要锁定也意味着塔我们不需要等待当前文件的请求完成(如果人们不断提出新的请求,可能需要无限期的时间)。唯一感兴趣的是第2步这将取决于该文件的投放 - 最简单的方法很可能是要么建立一个HTTP重定向或使用URL重写

HTTP重定向

HTTP重定向是在服务器通知客户在获取给定资源的请求时查看其他位置,以便浏览器URL自动更新以匹配新位置。例如,如果用户请求http://server/20120221.pdf,那么它们可以被自动重定向到另一个URL,例如http://server/20120221_v2.pdf(浏览器中显示的URL会改变,但是他们需要输入的URL不会)。

您可以使用httpRedirect配置元素在IIS 7中做到这一点,例如:

<configuration> 
    <system.webServer> 
     <httpRedirect enabled="true" exactDestination="true" httpResponseStatus="Found"> 
     <!-- Note that I needed to add a * in for IIS to accept the wildcard even though it isn't used in this case --> 
     <add wildcard="*20120221.pdf" destination="20120221_v2.pdf" /> 
     </httpRedirect> 
    </system.webServer> 
</configuration> 

所链接的页面显示如何从ASP.Net

URL重写更改这些设置

或者,IIS可以设置为自动提供给定URL的不同文件的内容,而无需客户端(浏览器)知道其差异。这称为URL重写,可以在IIS中使用类似this的方式完成,但它确实需要将其他组件安装到IIS才能正常工作。

使用HTTP重定向可能是最简单的方法。

+0

我的问题有两方面。 1)我不知道该怎么做。 2)文件名必须是YYYYMMDD.pdf格式,那么如何在仍服务旧文件的同时编写一个具有相同名称的* new *文件?如果你有例子,我愿意学习。 – pete 2012-02-21 16:30:18

+0

“是使用ASP.Net还是只是一个静态文件?”这只是一个静态文件。 – pete 2012-02-21 16:33:02

+0

@pete我已经更新了一些更详细的答案 – Justin 2012-02-21 17:06:32

相关问题