19
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【C#】ASP.NET Core で CSV ファイルを返す Web API を作る

Last updated at Posted at 2019-02-21

概要

ASP.NET CoreWeb APIを開発しクライアントにCSVファイルを返すエンドポイントを作ってみます。
TODOアプリでDBから取得したTODO一覧をCSVファイルとしてダウンロードできる機能を想定します。

プロジェクト構築

.NET Core CLIでプロジェクトのひな型を構築します。

# .NET Core SDK バージョンを確認
$ dotnet --version
2.1.502

# Web API プロジェクトを生成
$ dotnet new web api -o WebApiCsv

$ cd WebApiCsv
# CsvHelperパッケージをインストール
$ dotnet add package CsvHelper

csprojファイルは以下の通りです。

WebApiCsv.csproj
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <!--ついでに言語バージョンを C#7.3 に変更-->
    <LangVersion>7.3</LangVersion>
  </PropertyGroup>

  <ItemGroup>
    <Folder Include="wwwroot\" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="CsvHelper" Version="12.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.1.2" PrivateAssets="All" />
  </ItemGroup>

</Project>

開発

Todoモデルを作成します。

Models/Todo.cs
namespace WebApiCsv.Models {
  public class Todo {
    public int ID { get; set; }
    public string Title { get; set; }
    public bool IsDone { get; set; }
  }
}

データ取得を行うリポジトリを作成します。
今回は実際にDBにアクセスせず、ダミーデータを返します。

Data/TodoRepository.cs
using System.Collections.Generic;
using WebApiCsv.Models;

namespace WebApiCsv.Data {
  public class TodoRepository {
    // ダミーデータ
    static List<Todo> todos { get; } = new List<Todo> {
      new Todo { ID = 1, Title = "CSV返却の記事", IsDone = false },
      new Todo { ID = 2, Title = "IoCの記事", IsDone = false },
    };

    public List<Todo> List() => this.todos;
  }
}

Todo一覧CSVデータを取得するサービスクラスを作成します。

Services/TodoService.cs
using CsvHelper;
using System.Collections.Generic;
using System.IO;
using WebApiCsv.Data;
using WebApiCsv.Models;

namespace WebApiCsv.Services {
  public class TodoService {
    // サンプルなので DI せず直にインスタンス化
    readonly TodoRepository repository = new TodoRepository();

    public byte[] GetCsvContents() {
      List<Todo> todos = repository.List();

      using (var memory = new MemoryStream())
      using (var writer = new StreamWriter(memory))
      using (var csv = new CsvWriter(writer)) {
        csv.WriteRecords(todos);
        writer.Flush(); //StreamWriter.Flush を呼ばないとバッファーからメモリに書き込まれないので注意
        return memory.ToArray();
      }
    }
  }
}

最後にリクエストを受け付けるControllerクラスを作成します。

Controllers/TodosController.cs
using Microsoft.AspNetCore.Mvc;
using System;
using WebApiCsv.Services;

namespace WebApiCsv.Controllers {
  [Route("api/[controller]")]
  [ApiController]
  public class TodosController : ControllerBase {
    // サンプルなので DI せず直にインスタンス化
    readonly TodoService service = new TodoService();

    [HttpGet("export")]
    public FileContentResult Export() {
      byte[] csv = service.GetCsvContents();
      string fileName = $"ToDoList-{DateTime.Now:yyyyMMdd_HHmmss}.csv";
      return File(csv, "text/csv", fileName);
    }
  }
}

サーバーを立ち上げます。

$ dotnet run
Hosting environment: Development
Content root path: ~/WebApiCsv
Now listening on: https://localhost:5001
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

https://localhost:{ポート番号}/api/todos/exportにアクセスするとCSVファイルをダウンロードできます。

ToDoList-20190216_000315.csv
ID,Title,IsDone
1,CSV返却の記事,False
2,IoCの記事,False

項目をダブルクォートで囲む

Services/TodoServiceから抜粋
  public byte[] GetCsvContents() {
    List<Todo> todos = repository.List();

    using (var memory = new MemoryStream())
    using (var writer = new StreamWriter(memory))
    using (var csv = new CsvWriter(writer)) {
+     csv.Configuration.ShouldQuote = (field, context) => true;
      csv.WriteRecords(todos);
      writer.Flush();
      return memory.ToArray();
    }
  }
}
ToDoList-20190222_010807.csv
"ID","Title","IsDone"
"1","CSV返却の記事","False"
"2","IoCの記事","False"

ヘッダーのカラム名を変えたい

Models/Todo.cs
+ using CsvHelper.Configuration.Attributes;
  
  namespace WebApiCsv.Models {
    public class Todo {
      public int ID { get; set; }

+     [Name("タイトル")]
      public string Title { get; set; }

+     [Name("済")]
      public bool IsDone { get; set; }
    }
  }
ToDoList-20190222_011222.csv
"ID","タイトル","済"
"1","CSV返却の記事","False"
"2","IoCの記事","False"
19
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?