LoginSignup
21
20

More than 5 years have passed since last update.

Springboot でCSVをダウンロード

Last updated at Posted at 2018-09-24

SpringbootでCSVをダウンロードしてみます。日本語にも対応します。

1.依存関係

build.gradle
dependencies {
    compile('org.springframework.boot:spring-boot-starter-thymeleaf')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.webjars:jquery:3.3.1')
    compile('com.fasterxml.jackson.dataformat:jackson-dataformat-csv');
    runtime('org.springframework.boot:spring-boot-devtools')
    compileOnly('org.projectlombok:lombok')
    providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

jackson-dataformat-csvを使います

2.Helper

ダウンロードするときに、ファイル名を日本語に対応するためのヘルパークラスを作成します。

DownloadHelper.java
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriUtils;

@Component
public class DownloadHelper {
    private static final String CONTENT_DISPOSITION_FORMAT
         = "attachment; filename=\"%s\"; filename*=UTF-8''%s";
    public void addContentDisposition(HttpHeaders headers, String fileName)
            throws UnsupportedEncodingException {
        String headerValue = String.format(CONTENT_DISPOSITION_FORMAT,
                fileName, UriUtils.encode(fileName, StandardCharsets.UTF_8.name()));
        headers.add(HttpHeaders.CONTENT_DISPOSITION, headerValue);
    }

}

3.ダウンロードするデータ

Member.java
import java.util.Date;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

import lombok.Data;

@JsonPropertyOrder({"ID", "名前", "プロフィール", "更新日時"})
@Data
public class Member {
    @JsonProperty("ID")
    private Long id;
    @JsonProperty("名前")
    private String name;
    @JsonProperty("プロフィール")
    private String desc;
    @JsonProperty("更新日時")
    @JsonFormat(pattern = "yyyy/MM/dd HH:mm:ss")
    private Date modified;

    public Member() {}

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

4.Controller

CsvController.java
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.dataformat.csv.CsvGenerator;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;

@Controller
public class CsvController {

    @Autowired
    DownloadHelper downloadHelper;

    /**
     * CsvMapperで、csvを作成する。
     * @return csv(String)
     * @throws JsonProcessingException
     */
    public String getCsvText() throws JsonProcessingException {
        CsvMapper mapper = new CsvMapper();
        //文字列にダブルクオートをつける
        mapper.configure(CsvGenerator.Feature.ALWAYS_QUOTE_STRINGS, true);
        //ヘッダをつける
        CsvSchema schema = mapper.schemaFor(Member.class).withHeader();
        //メンバーデータをダウンロードするイメージ。本来はDBからデータを取得する。
        List<Member> members = new ArrayList<Member>();
        members.add(new Member(1L, "user01", "プロフィール1", new Date()));
        members.add(new Member(2L, "user02", "プロフィール2", new Date()));
        members.add(new Member(3L, "user03", "プロフィール3", new Date()));
        return mapper.writer(schema).writeValueAsString(members);
    }

    /**
     * csvをダウンロードする。
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/download/csv", method = RequestMethod.POST)
    public ResponseEntity<byte[]> download() throws IOException {
        HttpHeaders headers = new HttpHeaders();
        downloadHelper.addContentDisposition(headers, "日本語ファイル名.csv");
        return new ResponseEntity<>(getCsvText().getBytes("MS932"), headers, HttpStatus.OK);
    }
}

5.HTML

index.html
<!DOCTYPE html>
<html lang="ja" xmlns="http://www.w3.org/1999/xhtml"
    xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script th:src="@{/webjars/jquery/3.3.1/jquery.min.js}"></script>
</head>
<body>
<form id="csvform" method="post" th:action="@{/download/csv}">
    <input type="hidden" name="filename"/>
    <button type="submit">送信</button>
</form>
<script>
</script>
</body>
</html>

Postするだけのformです。

6.確認

(1)送信ボタンを押すと、ファイルがダウンロードされる。
image.png

ダウンロードしたファイルの内容

日本語ファイル名.csv
"ID","名前","プロフィール","更新日時"
1,"user01","プロフィール1","2018/09/24 07:28:57"
2,"user02","プロフィール2","2018/09/24 07:28:57"
3,"user03","プロフィール3","2018/09/24 07:28:57"

ファイル名、ファイルの値ともに、日本語も問題なく出力できました。

21
20
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
21
20