锁定替换网站上的文件的问题

时间:2009-12-02 00:07:55

标签: c# asp.net

我想用更新的版本替换IIS网站上的现有文件。假设这些文件是大型pdf文档,可以通过超链接访问。该网站全天候运行,因此我担心在某人尝试读取文件的同时更新文件时会出现锁定问题。

使用服务器上运行的C#代码更新文件。 我可以想到打开文件写两个选项。

选项1)使用FileShare.Read:

打开要写入的文件
using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))

当此文件处于打开状态,并且用户通过超链接请求同一文件在Web浏览器中阅读时,该文档将打开为空白页面。

选项2)使用FileShare.None打开要写入的文件:

using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) 

虽然此文件已打开,并且用户通过超链接请求在Web浏览器中读取同一文件,但浏览器显示错误。在IE 8中,您获得HTTP 500,“网站无法显示页面”,并且在Firefox 3.5中,您会得到:“进程无法访问该文件,因为它正由另一个进程使用。”

浏览器的行为有道理,看似合理。我想用户在更新文件的同时尝试读取文件的可能性极小。如果不知何故,文件更新是原子的,就像用事务处理的SQL更新数据库那样会很好。

我想知道你们是否担心这类事情,并且更喜欢上述任何一种选择,甚至还有其他选择来更新文件。

5 个答案:

答案 0 :(得分:1)

如何使用其他名称复制新版本的文件,然后File.Move()将覆盖参数设置为 true ?在您编写它时,您不会干扰Web服务器,并且移动文件会很快。

答案 1 :(得分:1)

我通常不担心这种问题,但你可以这样做:

  • 创建指向ASPX页面的链接,该页面下载参考文件,例如“Download.aspx?Name = Document1.pdf”
  • 在该页面中,在下载该文件之前,请查找名为“Updated”的文件夹
  • 如果找到它,请从中获取文件
  • 如果没有,请从“当前”文件夹
  • 获取

更新文件:

  • 创建文件夹名称“正在更新”
  • 将新文件复制到其中
  • 将其重命名为“已更新”(因此新下载将其用作来源)
  • 更新“当前”文件夹
  • 删除“已更新”文件夹

答案 2 :(得分:1)

一种选择是在超链接和文件之间构建一个额外的层。而不是直接链接到文件使超链接指向另一个页面(或类似的资源)。然后,该资源/页面可以确定哪个是需要发送到浏览器的最新文件,然后将其发送到浏览器。这样链接将始终相同,但文件可以更改。

答案 3 :(得分:1)

这本身就是一个线程问题,以干净的方式解决这些问题可能很棘手。从概念上讲,您希望从多个线程同步对文件的读写访问权限。

为了实现这一点,我会将文件存储在IIS的网站根目录之外,以便IIS不直接提供它。我会创建一个单独的HttpHandler来代替它。 HttpHandler会锁定写代码也会锁定的对象。您应该使用ReaderWriterLockSlim,以便可以进行多个并发读取(EnterReadLock),同时还确保只有一个写入线程可以执行(EnterWriteLock),并且在写入时会阻止读取。 / p>

答案 4 :(得分:0)

遇到类似问题,我开发了自己的解决方案(基本上有多个版本的文件,通过ASHX处理程序提供服务)。

see my CodeProject article讨论解决方案(以及可能的警告)