我想用更新的版本替换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更新数据库那样会很好。
我想知道你们是否担心这类事情,并且更喜欢上述任何一种选择,甚至还有其他选择来更新文件。
答案 0 :(得分:1)
如何使用其他名称复制新版本的文件,然后File.Move()将覆盖参数设置为 true ?在您编写它时,您不会干扰Web服务器,并且移动文件会很快。
答案 1 :(得分:1)
我通常不担心这种问题,但你可以这样做:
更新文件:
答案 2 :(得分:1)
一种选择是在超链接和文件之间构建一个额外的层。而不是直接链接到文件使超链接指向另一个页面(或类似的资源)。然后,该资源/页面可以确定哪个是需要发送到浏览器的最新文件,然后将其发送到浏览器。这样链接将始终相同,但文件可以更改。
答案 3 :(得分:1)
这本身就是一个线程问题,以干净的方式解决这些问题可能很棘手。从概念上讲,您希望从多个线程同步对文件的读写访问权限。
为了实现这一点,我会将文件存储在IIS的网站根目录之外,以便IIS不直接提供它。我会创建一个单独的HttpHandler来代替它。 HttpHandler会锁定写代码也会锁定的对象。您应该使用ReaderWriterLockSlim
,以便可以进行多个并发读取(EnterReadLock
),同时还确保只有一个写入线程可以执行(EnterWriteLock
),并且在写入时会阻止读取。 / p>
答案 4 :(得分:0)
遇到类似问题,我开发了自己的解决方案(基本上有多个版本的文件,通过ASHX处理程序提供服务)。
请see my CodeProject article讨论解决方案(以及可能的警告)