2009-12-02 49 views
1

我想用更新後的版本替換IIS網站上的現有文件。說這些文件是大型的pdf文件,可以通過超鏈接訪問。該站點全天候運行,因此我擔心在某人正在嘗試讀取文件的同時正在更新文件時會鎖定問題。鎖定網站上的文件替換問題

使用服務器上運行的C#代碼更新文件。 我可以考慮打開文件進行寫入的兩個選項。

選項1)打開寫入文件,使用FileShare.Read:

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

雖然這個文件是開放的,用戶請求相同的文件通過超鏈接,文檔在網絡瀏覽器閱讀作爲一個空白頁面打開。

選項2)使用FileShare.None打開寫入文件:

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

雖然這個文件是開放的,用戶請求相同的文件通過超鏈接,瀏覽器顯示在Web瀏覽器閱讀一個錯誤。在IE 8中,您獲得了HTTP 500,「網站無法顯示頁面」,並且在Firefox 3.5中,您會得到:「該進程無法訪問該文件,因爲該文件正在被另一個進程使用。」

瀏覽器的行爲類型有道理,看起來合理。我猜想用戶嘗試在更新文件的同時嘗試讀取文件的可能性非常小。如果以某種方式,文件更新是原子的,就像使用包裹在事務中的SQL更新數據庫一樣。

我想知道你們是否擔心這類事情,並且更喜歡上述選項之一,或者甚至有其他更新文件的選項。

回答

1

如何使用不同名稱複製文件的新版本,然後執行File.Move()將覆蓋參數設置爲true?當你寫它時,你不會干擾Web服務器,並且移動文件將很快。

+0

好吧,其實我結束了這是怎麼回事。雖然我看不到帶覆蓋參數的File.Move重載(我使用.net 2.0),但我必須首先明確調用File.Delete。最終用戶可以在瀏覽器中獲得「404文件未找到」錯誤的機會有一小段窗口,但這看起來不錯。 感謝所有人的回覆 - 他們可能會在未來需要時提供更強大的解決方案。 – 2009-12-02 02:44:14

+0

哦,對。它是File.Copy中的覆蓋參數。對於那個很抱歉。 – Gonzalo 2009-12-02 02:53:18

1

我通常不擔心這樣那樣的問題,但你可以工作圍繞這樣:

  • 創建一個鏈接到下載引用的文件的ASPX頁面,如「Download.aspx名稱=文檔1。PDF」
  • 在該頁面,下載前該文件中,尋找一個文件夾名爲‘更新’
  • 如果你找到它,從它那裏得到你的文件
  • 如果沒有,去得到它的‘當前’文件夾

要更新文件:

  • 創建一個文件夾名稱中的 「更新」
  • 新的文件拷貝到
  • 重命名爲「更新」(所以新下載使用它作爲源)
  • 更新您的「當前」文件夾
  • 刪除你的「更新」文件夾
1

一個選擇是建立之間的額外層超鏈接和文件。不是直接鏈接到文件,而是將超鏈接指向另一個頁面(或類似的資源)。然後,此資源/頁面可以確定哪個是需要發送到瀏覽器的最新文件,然後將其發送到瀏覽器。這種方式鏈接總是相同的,但文件可以改變。

1

這是一個線程問題的核心,這些可能是一個乾淨的方式來解決棘手。從概念上講,您想要從多個線程同步對文件的讀取和寫入訪問。

爲了達到這個目的,我將這個文件存儲在IIS的網站根目錄之外,以便IIS不直接提供它。我會創建一個單獨的HttpHandler來代替它。 HttpHandler會鎖定寫入代碼也會鎖定的對象。您應該使用ReaderWriterLockSlim,讓你可以有多個併發讀取(EnterReadLock),同時確保只有一個寫線程可以執行(EnterWriteLock)和讀取,而寫被封鎖。

+0

+1有趣的方法,ty – 2009-12-02 02:49:29

0

有一個類似的問題,我開發了自己的解決方案(基本上是有文件的多個版本,通過一個ASHX處理程序爲他們提供服務)。

see my CodeProject article討論解決方案(以及可能的警告)