2016-05-03 104 views
4

我遇到一個WebAPI方法的小問題,用戶在調用方法的路由時下載文件。Web API下載鎖文件

的方法本身是相當簡單:

public HttpResponseMessage Download(string fileId, string extension) 
{ 
    var location = ConfigurationManager.AppSettings["FilesDownloadLocation"]; 
    var path = HttpContext.Current.Server.MapPath(location) + fileId + "." + extension; 

    var result = new HttpResponseMessage(HttpStatusCode.OK); 
    var stream = new FileStream(path, FileMode.Open); 
    result.Content = new StreamContent(stream); 
    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); 
    return result; 
} 

的方法按預期工作 - 我第一次調用它。該文件被傳輸,我的瀏覽器開始下載文件。

但是 - 如果我無論從我自己的電腦或其他任何再次調用同一個網址 - 我得到一個錯誤說:

該進程無法訪問該文件 「d:\ ... \ App_Data \ pdfs \ test-file.pdf',因爲 正在使用另一個進程。

這個錯誤持續了大約一分鐘 - 然後我可以再次下載文件 - 但只有一次 - 然後我必須再等待一分鐘左右,直到該文件被解鎖。

請注意,我的文件相當大(100-800 MB)。

我在我的方法中丟失了什麼嗎?它幾乎看起來像流鎖定文件一段時間或類似的東西?

謝謝:)

回答

7

這是因爲你的文件是由第一個流鎖定,您必須指定一個FileShare,允許它由多個流被打開:

public HttpResponseMessage Download(string fileId, string extension) 
{ 
    var location = ConfigurationManager.AppSettings["FilesDownloadLocation"]; 
    var path = HttpContext.Current.Server.MapPath(location) + fileId + "." + extension; 

    var result = new HttpResponseMessage(HttpStatusCode.OK); 
    var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); 
    result.Content = new StreamContent(stream); 
    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); 
    return result; 
} 

就像你允許多個流打開這個文件爲只讀。

關於構造函數重載,請參閱MSDN documentation

+0

如果您在using語句中聲明流,它將在返回響應之前進行處理,並且下載將失敗。 –

+0

你是救生員法比安!這樣一個簡單的解決方案 - 我只是盯着自己盲目:) 我也想過使用陳述 - 但正如你所說,它沒有任何意義,因爲它會在回電前處理。 非常感謝! :) – JBuus

+2

@JBuus不客氣。文件流將在內容流盡快處理,事實上應該在客戶端讀取響應時完成。 –