前言
產品經理有一個需求,就是將cosmosDB里的數據,導出到Excel中.
1.新建一個.net core web api controller
添加引用:EPPlus.Core
Install-Package EPPlus.Core
命名空間:
using OfficeOpenXml;
2.在HomeController里添加Export的方法
這里會遇到幾個坑:
第一個是使用HttpResponseMessage的時候,返回的不是一個文件,而是一個HttpResponseMessage 類型的json;
第二個是 返回的File的時候,注意要加上stream.position=0;
第三個是將stream保存在內存(小文件),有些虛機不一定有C盤,所以創建物理路徑是存在risk,暫存在內存避免crash。要是大文件還是另尋他法,萬一out of memory。
這里我們使用IActionResult返回類型。
[HttpGet]
[Route("export")]
public async Task<IActionResult> Export()
{
string fileName = $"{Guid.NewGuid().ToString()}.xlsx";
//store in memory rather than pysical directory
var stream = new MemoryStream();
var messages = await ConversationManager.GetConversationMessagesAsync();
var columns = new ConversationMessage();
using (ExcelPackage package = new ExcelPackage(stream))
{
// add worksheet
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Conversation Message");
//add head
worksheet.Cells[1, 1].Value = "From Id";
worksheet.Cells[1, 2].Value = "To Id";
worksheet.Cells[1, 3].Value = "Message";
worksheet.Cells[1, 4].Value = "Time";
worksheet.Cells[1, 5].Value = "Attachment";
worksheet.Cells[1, 6].Value = "Conversation Id";
//add value
var rowNum = 2; // rowNum 1 is head
foreach (var message in messages)
{
worksheet.Cells["A" + rowNum].Value = message.FromId;
worksheet.Cells["B" + rowNum].Value = message.ToId;
worksheet.Cells["C" + rowNum].Value = message.Message;
worksheet.Cells["D" + rowNum].Value = message.MsgTime;
worksheet.Cells["E" + rowNum].Value = message.Attachment;
worksheet.Cells["F" + rowNum].Value = message.ConversationId;
rowNum++;
}
package.Save();
}
stream.Position = 0;
return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName);
}
3.說明
最后在瀏覽器打開api,成功下載:
這里highlighted的部分就是代碼中的Worksheets,還可以對表頭進行加粗上色之類的,暫時沒有這個需求就不深入了。
一開始使用如下方式:
[HttpGet]
public HttpResponseMessage DownloadFile(string fileName)
{
if (!string.IsNullOrEmpty(fileName))
{
string filePath = "/images/";
string fullPath = AppDomain.CurrentDomain.BaseDirectory + filePath + "/" + fileName;
if (File.Exists(fullPath))
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
var fileStream = new FileStream(fullPath, FileMode.Open);
response.Content = new StreamContent(fileStream);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = fileName;
return response;
}
}
return new HttpResponseMessage(HttpStatusCode.NotFound);
}
ContentDisposition會出現為null的情況,就沒有FileName,所以這一步就已經exception了。
但貌似並不能成功下載(打開api,直接下載並顯示在瀏覽器下方)