常規下載
控制器自帶的 FileContentResult 可以讓我們很方便的返回文件到服務端,減少了很多步驟。用於下載文件的時候,像視頻、文本、圖片這種瀏覽器支持的文件,默認就會被瀏覽器打開。這時候想讓它變成下載,還需要設置一下響應頭,告訴瀏覽器如何處理才行。
public ActionResult DownLoadFile(String path, string fileName, string contentType) { Response.AddHeader("Content-Disposition", "attachment; filename=" + Server.UrlEncode(fileName)); return File(path,contentType); }
以上,在js使用 location.href = fileDownloadUrl 這樣簡單的方式即可實現在asp.net mvc5下載文件。關鍵是這個Content-Disposition,它的內容大概就是說明以什么方式處理,默認的文件名是什么。attachment 是以附件方式處理的意思,后面的就是文件名了,url編碼處理之后可以避免那些因為帶空格的文件名等等帶來的問題。
斷點續傳下載
public void FileRangeDownload() {string fileName = "lubuntu-19.04-desktop-amd64.iso"; //客戶端保存的文件名 string filePath = Server.MapPath($"./{fileName}");//要被下載的文件路徑 var range = Request.Headers["Range"]; // Range 一般是"bytes=397506944-" if (!string.IsNullOrWhiteSpace(range))//如果遵守協議,支持斷點續傳 { using (StreamReader reader = new StreamReader(System.IO.File.OpenRead(filePath))) { var fileLength = new FileInfo(filePath).Length; //文件的總大小 fileLength = reader.BaseStream.Length; long begin; //文件的開始位置 long end; //文件的結束位置 long.TryParse(range.Split('=')[1].Split('-')[0], out begin); long.TryParse(range.Split('-')[1], out end); end = end - begin > 0 ? end : (fileLength - 1); //表頭 表明 下載文件的開始、結束位置 和文件總大小 Response.AddHeader("Content-Range", "bytes " + begin + "-" + end + "/" + fileLength); Response.ContentType = "application/octet-stream"; Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName); Response.StatusCode = 206; Response.TransmitFile(filePath, begin, (end - begin + 1)); //發送 文件開始位置讀取的大小 } } else { Response.ContentType = "application/octet-stream"; Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName); Response.TransmitFile(filePath); } }
注意點是從請求頭讀取Range,獲得本次請求客戶需要下載的區間,如果沒有的話就是直接下載,如果有的話注意響應狀態修改206,表示返回的內容是部分內容,否則斷點續傳繼續下載可能重新下載。另外Last-Modified、ETag可用來標記資源是否更新,從而決定是否重新下載,這里不做演示。
題外話,這個通過設置響應頭來保證文件以附件形式下載的功能早在一年前就用過一次,當時看了一臉懵,也沒記下來詳細了解,現在又用到了,模模糊糊只記得好像在哪用過一次,當然不記得怎么寫了,網上搜,一時又找不到,還是得自己一碼一字的敲下來,這樣印象深刻而且以后又容易找。什么轉載啊,復制粘貼的都是浮雲,誰碼誰知道!