2012-02-21 40 views
1

問題:如何覆蓋/更新當前由IIS提供的文件?

我的公司推出了我在我們內部網站上託管的每月通訊。我有一個通訊作者的頁面上傳最新版本。一旦作者上傳了最新的時事通訊,他就會發送廣播電子郵件來宣佈新的時事通訊。員工總是檢查新的時事通訊並向作者發送反饋,並進行更正。

一旦作者做出必要的修正(通常發送廣播電子郵件的一個小時內),他再次訪問我的網頁,並替換最新版本與更新的通訊。

緊隨更換(或更新,如果你願意)的通訊的,任何人試圖訪問它得到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是存儲在ViewState
  • dr("File").ToString一個DataTable是文件名(無路徑)
  • dr("Path").ToString是完整的本地機器路徑和文件名(即,C:\ APP_ROOT \通訊\檔案\ 20120214.pdf')
  • 的通訊的文件名設置爲‘YYYYMMDD.pdf’其中YYYYMMDD是上傳的日期(格式)。

在任何情況下,我敢肯定,上面的代碼是不建立文件上的獨佔鎖,以使文件可以被安全地覆蓋。

最後,我想,以確保發生以下情況:

  1. 如果IIS現任文件,等到IIS完成服務它。
  2. 之前IIS可以再次提供服務的文件,該文件確立的排他鎖,這樣其他進程,線程,用戶(等)無法讀取或寫入文件。
  3. 刪除該文件完全譜寫新的文件來替換它或覆蓋與新內容的現有文件。
  4. 刪除獨佔鎖以便用戶可以再次訪問文件。

建議?

此外,我可以使用Mutex獲取Windows文件系統中文件的互斥鎖嗎?

預先感謝您爲您的幫助和建議。

編輯:

,對於產生的通訊鏈路是基於物理文件名的方式。使用的方法是:

  1. 獲取「存檔」目錄中的所有PDF文件。對於每個文件:
  2. 解析公佈的從文件名的日期。
  3. 店日期,文件路徑,文件名,並在DataTable
  4. 排序DataTable按日期(降序)的URL的每個文件在DataRow
  5. 輸出第一行作爲當前問題。
  6. 輸出所有後續行作爲「檔案」按年份和月份舉辦。

UPDATE

代替不能夠在該文件中的所有現有請求已經完成辨別的,我接過仔細看看@賈斯汀的回答(「你的互斥的第一部分將只有在從文件中讀取的進程也獲得相同的互斥量時纔有效果。「)

這導致我在Configure IIS7 to server static content through ASP.NET Runtime和被接受的答案中鏈接的文章。

爲此,我對所有實現New Mutex(True, "MyMutexToPreventReadsOnOverwrite")的PDF文件實施了一個處理程序,以確保在任何給定時間只有一個線程正在使用PDF進行操作。

謝謝你的回答,@Justin。雖然我沒有結束使用您建議的實現,但您的回答指向我一個可接受的解決方案。

+0

我添加了c#標籤,因爲我可以讀取c#並將其翻譯回vb.net。隨意在c#中發佈代碼。 – pete 2012-02-21 16:37:04

+0

所有應有的尊重 - 這是愚蠢的。爲什麼不只是1)上傳到「暫存區域」(即*始終*可寫入),然後2)複製 - 在「正在使用文件」錯誤時「重試」? – paulsm4 2012-02-21 16:48:15

回答

3

你互斥纔會有效果,如果從文件讀取過程中也得到相同的互斥。用於提供文件的方法是什麼?是使用ASP.Net還是隻是一個靜態文件?

我的工作流程將是一個有點不同:

  1. 寫入新的通訊到文件
  2. 有IIS開始提供了新的文件,而不是舊的給定的通訊地址
  3. 刪除舊文件,一旦該文件的所有現有請求已經完成

這不需要鎖定也意味着塔我們不需要等待當前文件的請求完成(如果人們不斷提出新的請求,可能需要無限期的時間)。唯一感興趣的是第2步這將取決於該文件的投放 - 最簡單的方法很可能是要麼建立一個HTTP重定向或使用URL重寫

HTTP重定向

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

URL重寫更改這些設置

或者,IIS可以設置爲自動提供給定URL的不同文件的內容,而無需客戶端(瀏覽器)知道其差異。這稱爲URL重寫,可以在IIS中使用類似this的方式完成,但它確實需要將其他組件安裝到IIS才能正常工作。

使用HTTP重定向可能是最簡單的方法。

+0

我的問題有兩方面。 1)我不知道該怎麼做。 2)文件名必須是YYYYMMDD.pdf格式,那麼如何在仍服務舊文件的同時編寫一個具有相同名稱的* new *文件?如果你有例子,我願意學習。 – pete 2012-02-21 16:30:18

+0

「是使用ASP.Net還是隻是一個靜態文件?」這只是一個靜態文件。 – pete 2012-02-21 16:33:02

+0

@pete我已經更新了一些更詳細的答案 – Justin 2012-02-21 17:06:32

相關問題