问题:
我公司发布了一份月刊,我在内部网站上发布。我有一个页面供新闻稿的作者上传最新版本。一旦作者上传了最新的时事通讯,他就会发送一封广播电子邮件来宣布新的时事通讯。员工总是查看新的简报并将反馈发送给作者,并进行必要的更正。
一旦作者进行了必要的更正(通常在发送广播电子邮件的一小时内),他就会重新访问我的页面,并用最新的简报替换最新版本。
在更新(或更新,如果你愿意)新闻通讯之后,任何试图访问它的人都会立即获得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
是存储在DataTable
ViewState
dr("File").ToString
是文件名(无路径)dr("Path").ToString
是完整的本地计算机路径和文件名(即'C:\ App_Root \ Newsletters \ archives \ 20120214.pdf')在任何情况下,我都非常确定上面的代码是而不是在文件上建立一个独占锁,以便可以安全地覆盖该文件。
最后,我想确保发生以下情况:
建议?
另外,我可以使用Mutex
来获取Windows文件系统中文件的互斥锁吗?
提前感谢您的帮助和建议。
修改
生成简报的链接的方式基于物理文件名。使用的方法是:
DataRow
DataTable
中的每个文件中
DataTable
(降序)。更新:
代替无法辨别该文件的所有现有请求何时完成,我仔细研究了@Justin的答案的第一部分(“你的互斥体只会在从文件也获得相同的互斥锁。“)
这导致我Configure IIS7 to server static content through ASP.NET Runtime以及已接受答案中的链接文章。
为此,我为所有实现New Mutex(True, "MyMutexToPreventReadsOnOverwrite")
的PDF文件实现了一个处理程序,以确保在任何给定时间只有一个线程正在对PDF做一些事情。
谢谢你回答,@ Justin。虽然我没有使用你建议的实现,但你的答案指向了我可接受的解决方案。
答案 0 :(得分:3)
只有从文件中读取的进程也获得相同的互斥锁时,您的互斥锁才会生效。用于提供文件的方法是什么?是使用ASP.Net还是仅仅是一个静态文件?
我的工作流程会有所不同:
这不需要锁定,也意味着我们不需要等待完成当前文件的请求(如果人们继续发出新请求,这可能会花费无限的时间)。唯一有趣的是第2步,它将取决于文件的服务方式 - 最简单的方法可能是设置HTTP重定向或使用URL重写
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
更改这些设置另外,IIS可以设置为自动提供给定URL的不同文件的内容,而客户端(浏览器)不知道其中的差异。这称为URL重写,可以使用this之类的东西在IIS中完成,但它确实需要在IIS上安装其他组件才能工作。
使用HTTP重定向可能是最简单的方法。