> ## Content Index
> Fetch the complete content index at: https://blog.anthea.day/llms.txt
> Use this file to discover other available public pages before exploring further.

# File Result：傳送 CSV 檔案實體和測試
- URL: https://blog.anthea.day/dotnet-file-result/
- Published: 2022-10-22T18:25:11.000Z
- Updated: 2026-11-07T14:51:01.000Z
- Author: Anthea / 芫荽
- Tags: #Migrated-1792241843742, #Import 2026-10-17 12:57, Coding, .NET

#### 目錄

- 傳送檔案實體：CSV
- Unit Test

---

### 傳送檔案實體

使用者有時候需要下載資料，對我而言最簡單直接的方式是在 server 端存成檔案之後，把連結回傳給前端，讓瀏覽器另開 URL 進行下載。好處是能保存使用者的下載紀錄，壞處是會占用空間，所以想找找看有沒有不需要存成檔案的方法。

傳送實體的方式很簡單：

```C#
using System.Net.Mime;
using System.Text;
using Microsoft.AspNetCore.Mvc;

namespace download_file.Controllers;

[ApiController]
[Route("api/[controller]")]
public class DownloadController : ControllerBase
{
    [HttpPost]
    public async Task<IActionResult> Download()
    {
        var mediaType = MediaTypeNames.Application.Octet;
        var buffer = await CreateContent();
    
        return File(buffer, mediaType);
    }

    private async Task<byte[]> CreateContent()
    {
        using var buffer = new MemoryStream();
        await using var sw = new StreamWriter(buffer, Encoding.UTF8);
        await sw.WriteLineAsync("Key,Value");
        await sw.WriteLineAsync("Id,123");
        await sw.FlushAsync();
        await buffer.FlushAsync();
        buffer.Position = 0;
        return buffer.ToArray();
    }
}
```

簡單的前端頁面接取：

```HTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>下載測試</title>
</head>
<body>
<div id="app">
    <button type="button" @click.prevent="download">下載</button>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/axios@1.1.2/dist/axios.min.js"></script>
<script>
    const app = Vue.createApp({
       methods:{
           download(){
               axios({
                   method: 'post',
                   url: './api/download'
               }).then(res => {
                   const url = window.URL
                       .createObjectURL(new Blob([res.data]));
                   console.log(res)
                   const link = document.createElement('a');
                   link.href = url;
                   link.setAttribute('download', `result.csv`);
                   document.body.appendChild(link);
                   link.click();
                   document.body.removeChild(link);
                   alert('下載成功');
               })
           },
       }, 
    });
    app.mount('#app');
</script>
</body>
</html>
```

下載成功的 `Console.log`：

![](https://blog.anthea.day/content/images/2026/10/1-csl2ius9duqhcab7pj6mjw.png)

---

### Unit Test

對於最近在練習單元測試的我，這是一個很棒的挑戰：如何幫檔案下載寫一個小小的測試。其中重要也最困難的應該是如何接到檔案，以及取得檔案的內容：

這邊要注意的是第 17 行中，要將 response 轉換成 `FileContentResult` 的部分，他會根據你原本在 Controller 中所回傳類型而有不同：

```C#
using System.Net.Mime;
using System.Text;
using download_file.Controllers;
using Microsoft.AspNetCore.Mvc;

namespace TestProject2;

public class Tests
{
    [Test]
    public async Task download_file_success()
    {
        var content = await GivenContentStream();
        var downloadController = new DownloadController();
        var response = await downloadController.Download();
        
        var result = response as FileContentResult;
        Assert.AreEqual(MediaTypeNames.Application.Octet, result.ContentType);
        Assert.AreEqual(content, result.FileContents);
    }

    private async Task<byte[]> GivenContentStream()
    {
        using var buffer = new MemoryStream();
        await using var sw = new StreamWriter(buffer, Encoding.UTF8);
        await sw.WriteLineAsync("Key,Value");
        await sw.WriteLineAsync("Id,123");
        await sw.FlushAsync();
        await buffer.FlushAsync();
        buffer.Position = 0;
        return buffer.ToArray();
    }
}
```

- `new File(byte[], …)` 要對應 `FileContentResult`
- `new File(stream, …)` 要對應 `FileStreamResult`

---

### References

- [How to Export CSV file from ASP.NET core](https://stackoverflow.com/questions/52741533/how-to-export-csv-file-from-asp-net-core?ref=blog.anthea.day)
- [Saving binary data as file using JavaScript from a browser](https://stackoverflow.com/questions/23451726/saving-binary-data-as-file-using-javascript-from-a-browser/23451803?ref=blog.anthea.day#23451803)
- [Difference between FileContentResult and FileStreamResult](https://stackoverflow.com/questions/34498184/difference-between-filecontentresult-and-filestreamresult?ref=blog.anthea.day)