代码之家  ›  专栏  ›  技术社区  ›  Moe Sisko

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

  •  1
  • Moe Sisko  · 技术社区  · 15 年前

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

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

    选项1)使用fileshare打开要写入的文件。读取:

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

    当打开此文件,并且用户通过超链接请求在Web浏览器中读取同一文件时,文档将以空白页打开。

    选项2)使用fileshare打开要写入的文件。无:

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

    当此文件打开时,用户通过超链接请求在Web浏览器中读取同一文件,浏览器将显示一个错误。在IE8中,你会得到HTP500,“网站无法显示页面”,在火狐3.5中,你会得到:“进程无法访问文件,因为它正被另一个进程使用。”

    浏览器的行为有点道理,而且似乎是合理的。我想用户不太可能在更新文件的同时尝试读取文件。如果文件更新是原子的,比如用围绕事务的SQL更新数据库,那就太好了。

    我想知道你们是否担心这类事情,更喜欢上面的任何一个选项,或者甚至有自己的其他选项来更新文件。

    5 回复  |  直到 15 年前
        1
  •  1
  •   Gonzalo    15 年前

    用不同的名称复制文件的新版本,然后执行 File.Move() 将overwrite参数设置为 ?当你写它的时候,你不会干扰网络服务器,移动文件会很快。

        2
  •  1
  •   Rubens Farias    15 年前

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

    • 创建一个指向下载引用文件的aspx页面的链接,如“download.aspx”。名称=document1.pdf“
    • 在该页面中,在下载该文件之前,请查找名为“已更新”的文件夹。
    • 如果你找到了,就从中获取你的文件
    • 如果没有,从“当前”文件夹中获取

    要更新文件:

    • 创建文件夹名“更新”
    • 将新文件复制到其中
    • 将其重命名为“已更新”(因此新下载将其用作源)
    • 更新您的“当前”文件夹
    • 删除“更新”文件夹
        3
  •  1
  •   jvilalta    15 年前

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

        4
  •  1
  •   G-Wiz RameshVel    15 年前

    这在本质上是一个线程问题,而这些问题可能难以以干净的方式解决。从概念上讲,您希望从多个线程同步对文件的读写访问。

    为了实现这一点,我将把文件存储在IIS的网站根目录之外,这样IIS就不会直接为它服务。我将创建一个单独的httphandler来代替它。httphandler将锁定写入代码也将锁定的对象。你应该使用 ReaderWriterLockSlim 这样就可以有多个并发读取( EnterReadLock )同时确保只有一个写线程可以执行( EnterWriteLock )而读操作在写操作时会被阻塞。

        5
  •  0
  •   Uwe Keim    15 年前

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

    拜托 see my CodeProject article 讨论解决方案(以及可能的注意事项)