#PostmanでエクセルをPOSTし、Spring側でCSV出力
末尾の参考サイトのソースをもとに、PostmanでExcelをPOSTし、受信側(spring boot)でCSVライブラリの「OrangeSignal CSV」を利用してCSV出力した。
CSVのヘッダに日本語の列名を指定するところで物凄くつまったので、サンプルソースを記載する。
@Service
public class ExcelService {
@Autowired TutorialRepository repository;
public void save(MultipartFile file) {
try {
List<Tutorial> tutorials = ExcelHelper.excelToTutorials(file.getInputStream());
repository.saveAll(tutorials);
// 区切り文字と囲み文字、エスケープ文字を指定して CSV 形式設定情報を構築
CsvConfig cfg = new CsvConfig(',', '"', '"');
List<TutorialCSVData> tutorialCSVList =
tutorials.stream().map(TutorialCSVData::toCSVDataFromPOJO).collect(Collectors.toList());
File fileout = new File("Tutorial.csv");
Csv.save(
tutorialCSVList,
fileout,
cfg,
new CsvEntityListHandler<TutorialCSVData>(TutorialCSVData.class));
} catch (Exception e) {
throw new RuntimeException("fail to store excel data: " + e.getMessage());
}
}
public ByteArrayInputStream load() {
List<Tutorial> tutorials = repository.findAll();
ByteArrayInputStream in = ExcelHelper.tutorialsToExcel(tutorials);
return in;
}
public List<Tutorial> getAllTutorials() {
return repository.findAll();
}
}
「OrangeSignal CSV」では、CSV出力にPOJOクラスが利用できる。
POJOクラスでは、@CsvEntity アノテーションと @CsvColumn アノテーションをつける。
@CsvColumn(name = "番号")とすると、CSVのヘッダ列の名前に"番号"を指定できる。
この指定をしない場合、CSVのヘッダ列の名前は、POJOクラスのフィールド名(この例では"id")となる。
参考元ソースには、データベースに格納する「Tutorial」Entityがあるが、
CSVに日本語項目を出力したかったので、別途「TutorialCSVData 」を作成し、TutorialからTutorialCSVDataに変換している。
OrangeSignal CSVサイトのユーザーガイドにある「ColumnNameMappingBeanListHandler」を使って、
項目列とPOJOオブジェクトフィールド(の変数名)を対応付けていたが、CSVの列が100以上の場合はしんどい。
100項目の定義をしたくないので、なんとかならないか調べたところ、@CsvEntityを使っている場合は、
「CsvEntityListHandler」を使えばよいということがわかった。
ここはユーザーガイドにも説明があるので、私の理解力がなかったようです。(ちょっと試してうまくいかなかったのであきらめてた)
将来、同じように困る人用にサンプルを載せておきます。
ちなみに公式のユーザーガイドにあるColumnNameMappingBeanListHandler#addColumnメソッドは誤記で、正しくはcolumnメソッドでした。詳細はJavadoc参照。
package com.bezkoder.spring.files.excel.model;
import com.orangesignal.csv.annotation.CsvColumn;
import com.orangesignal.csv.annotation.CsvEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@CsvEntity
public class TutorialCSVData {
@CsvColumn(name = "番号")
public String id;
@CsvColumn(name = "タイトル")
public String title;
@CsvColumn(name = "詳細")
public String description;
@CsvColumn(name = "補足")
public String published;
public static TutorialCSVData toCSVDataFromPOJO(Tutorial tutorial) {
return new TutorialCSVData(
Long.toString(tutorial.getId()),
tutorial.getTitle(),
tutorial.getDescription(),
String.valueOf(tutorial.isPublished()));
}
}
CsvConfigクラスで””で囲ったり、改行コード(WIN, Mac, Linux)を指定できる。
#CSV出力結果
"番号","タイトル","詳細","補足"
"1","Spring Boot Tut#1","Tut#1 Description","false"
"2","Spring Boot Tut#2","Tut#2 Description","true"
"3","MySQL Database Tut#3","Tut#3 Description","true"
"4","Hibernate Tut#4","Tut#4 Description","false"
"5","Spring Cloud Tut#5","Tut#5 Description","true"
"6","Microservice Tut#6","Tut#6 Description","false"
"7","MongoDB Database Tut#7","Tut#7 Description","true"
"8","Spring Data JPA Tut#8","Tut#8 Description","true"
#補足情報
「OrangeSignal CSV」利用のためのpom.xmlの設定です。
<dependency>
<groupId>com.orangesignal</groupId>
<artifactId>orangesignal-csv</artifactId>
<version>2.2.1</version>
</dependency>
公式のクイックスタートではバージョンが「2.2.2-SNAPSHOT」となってますが、
Intellij環境ではmavenのエラーになり、読み込まれませんでした。
参考:
Spring Boot: Upload/Import Excel file data into MySQL Database
https://www.bezkoder.com/spring-boot-upload-excel-file-database/
ソースを動かす場合、エクセルのシート名は
ExcelHelperクラスのSHEETで「Tutorials」に定義されているので注意。(POSTするエクセルのシート名に変更)
OrangeSignal CSV
http://orangesignal.github.io/orangesignal-csv/index.html
https://github.com/orangesignal/orangesignal-csv/issues/29
おわり。