最近使用.Net core 3.1 翻新系統時,遇到了個問題, 原本只是很單純的下個Web API 到後端取檔案再return回前端, .Net Framework 4.5.2 中的寫法是這樣:
[Route("downloadfile")] [HttpPost()] public HttpResponseMessage DownloadFile([FromBody] string fileName) { var filePath = "C:\\Template.xlsx"; HttpResponseMessage result = new HttpResponseMessage { StatusCode = HttpStatusCode.OK }; result.Content = new StreamContent(new FileStream(filePath, FileMode.Open, FileAccess.Read)); result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = Path.GetFileName(filePath) }; result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.ms-excel"); return result; }
假設我們要從後端取得一個Template.xlsx檔案,返回一個HttpResponseMessage類型,用開發者工具看到response的結果,會收到:
但在.Net core底下用相同的方式return HttpResponseMessage:
(跟.net framwork中一模一樣的寫法)
[Route("downloadfile")] [HttpPost()] public HttpResponseMessage DownloadFile([FromBody] string fileName) { var filePath = "C:\\Template.xlsx"; HttpResponseMessage result = new HttpResponseMessage { StatusCode = HttpStatusCode.OK }; result.Content = new StreamContent(new FileStream(filePath, FileMode.Open, FileAccess.Read)); result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = Path.GetFileName(filePath) }; result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.ms-excel"); return result; }
response只會顯示一串Json格式的資料,回傳的是序列化的結果:
Content-Length很小,看起來沒有夾帶任何檔案內容:
查了一下官方文件:
HttpResponseMessage也適用於.Net core 3.1阿!!!
到底發生什麼事了?!
.net core的Web API中,把HttpResponseMessage當成一個model來處理,所以使用HttpResponseMessage會是返回Json。參考資料
可以參考此說明。
但我沒有很喜歡多去增加套件的方法,所以使用的是後面幾種解法。
直接把File檔案返回給前端的方式,在.Net core中做起來也是沒有問題的:
[Route("downloadfile")] [HttpPost()] public ActionResult DownloadFile([FromBody] string fileName) { var filePath = "C:\\Template.xlsx"; var bytes = System.IO.File.ReadAllBytes(filePath); return File(bytes, "application/vnd.ms-excel", Path.GetFileName(filePath)); }
考量到後端檔案讀取時間,也可以使用非同步的方式返回。
[Route("downloadfile")] [HttpPost()] public async Task<ActionResult> DownloadFile([FromBody] string fileName) { var filePath = "C:\\Template.xlsx"; var bytes = await System.IO.File.ReadAllBytesAsync(filePath); return File(bytes, "application/vnd.ms-excel", Path.GetFileName(filePath)); }
[Route("downloadfile")] [HttpPost()] public IActionResult DownloadFile([FromBody] string fileName) { var filePath = "C:\\Template.xlsx"; var result = new FileStream(filePath, FileMode.Open); return new FileStreamResult(result, "application/vnd.ms-excel"); }
若你想夾帶Content,可以返回FileContentResult:
[Route("downloadfile")] [HttpPost()] public IActionResult DownloadFile([FromBody] string fileName) { var filePath = "C:\\Template.xlsx"; var result = new FileContentResult(System.IO.File.ReadAllBytes(filePath), "application/vnd.ms-excel") { FileDownloadName = Path.GetFileName(filePath) }; return result; }
記得需於Startup.cs增加Policy,將Content-Disposition加入回傳的Header中:
//Startup.cs services.AddCors(options => { options.AddPolicy("CorsPolicy", policy => { policy.WithOrigins("http://localhost:4200") .WithExposedHeaders("Content-Disposition"); }); });
以上是翻新系統採到的小雷,希望對大家有幫助,內容有誤的話再請大家多多指教!