LoginSignup
62
71

More than 5 years have passed since last update.

Spring MVC で CSV をダウンロードさせる

Posted at

思った以上にかんたんに実装できたわりに、ネット上にちょうどいい塩梅のサンプルが転がっていなかったのでメモ。

なお、今回のデモコードの全文は以下にありますので、実際の挙動を確認したい場合はご利用ください。
https://github.com/yo1000/com.yo1000.edu.boot.octetstream

環境

  • Java 1.8.0_91
  • Maven 3.3.9 (Maven wrapper)
  • Spring Boot 1.4.1.RELEASE
$ ./mvnw --version
Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-11T01:41:47+09:00)
Maven home: /Users/yo1000/.m2/wrapper/dists/apache-maven-3.3.9-bin/2609u9g41na2l7ogackmif6fj2/apache-maven-3.3.9
Java version: 1.8.0_91, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre
Default locale: ja_JP, platform encoding: UTF-8
OS name: "mac os x", version: "10.11.6", arch: "x86_64", family: "mac"

依存関係の追加

jackson-dataformat-csv を使うと、不要な依存を追加せず、かんたんに実現できるので、今回はこれを使用します。(spring-boot-starter-parent で、デフォルトバージョンが設定されているため、バージョン指定は不要です。)

pom.xml (抜粋)
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.4.1.RELEASE</version>
  <relativePath/> <!-- lookup parent from repository -->
</parent>

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-csv</artifactId>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>

モデルの実装

今回はわかりやすいように、かんたんなモデルを作成します。

@JsonProperty で設定した値が、CSV の1行目に出力されます。設定しない場合はフィールド名が出力されます。
また、@JsonPropertyOrder を設定しない場合は、プロパティ名でソートされた順に出力されてしまうので、任意の順番で出力したい場合には注意が必要です。

Demo.java
package com.yo1000.edu.boot.octetstream.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import java.util.Date;

@JsonPropertyOrder({"ID", "名前", "概要", "更新日時"})
public class Demo {
    @JsonProperty("ID")
    private Long id;
    @JsonProperty("名前")
    private String name;
    @JsonProperty("概要")
    private String desc;
    @JsonProperty("更新日時")
    private Date modified;

    public Demo() {}

    public Demo(Long id, String name, String desc, Date modified) {
        this.id = id;
        this.name = name;
        this.desc = desc;
        this.modified = modified;
    }

    // Getter/Setter
}

コントローラーの実装

Object <-> JSON の変換に、ObjectMapper を使うように、ここでは CsvMapper というクラスを使用して、オブジェクトを CSV に変換します。

@GetMapping の、produces 属性に、"application/octet-stream"(MediaType.APPLICATION_OCTET_STREAM_VALUE) と、"Content-Disposition: attachment" を、セミコロンで区切って指定することで、ダウンロードダイアログつきで、CSV を出力できます。
また、charset を指定することで、出力する CSV ファイルの文字セットも変更することができます。デフォルトが UTF-8 なので、今回はあえて Shift_JIS を指定してみます。

また、ダウンロードされるファイルのデフォルトの名前は URL に準じるため、"*.csv" という URL を割り当てておくだけで、リクエストされたファイル名でそのままダウンロードさせることが可能になります。

CsvController.java
package com.yo1000.edu.boot.octetstream.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import com.yo1000.edu.boot.octetstream.model.Demo;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Controller
@RequestMapping("csv")
public class CsvController {
    @GetMapping(value = "*.csv",
            produces = MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=Shift_JIS; Content-Disposition: attachment")
    @ResponseBody
    public Object getCsv() throws JsonProcessingException {
        List<Demo> demos = new ArrayList<Demo>() {
            {
                add(new Demo(1001L, "aaa", "xxx", new Date()));
                add(new Demo(1002L, "bbb", "yyy", new Date()));
                add(new Demo(1003L, "ccc", "zzz", new Date()));
            }
        };

        CsvMapper mapper = new CsvMapper();
        CsvSchema schema = mapper.schemaFor(Demo.class).withHeader();
        return mapper.writer(schema).writeValueAsString(demos);
    }
}

動作の確認

実際の動きを見てみましょう。

作成したエンドポイントをリクエストしてみます。
スクリーンショット 2016-10-03 19.37.19.png

ダウンロードダイアログが現れました!
スクリーンショット 2016-10-03 19.37.45.png

ダウンロードしたファイルを開いてみると、Shift JIS にて、文字化けなく内容を表示できていることがわかります。
スクリーンショット 2016-10-03 19.45.19.png

以上のように、これまでどおりのコントローラー記述と、jackson-dataformat-csv を使用して、かんたんに CSV ファイルを出力することができました。Spring では、オブジェクトの変換に Jackson が使用されているので、うまく活用していきたいですね。

62
71
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
62
71