🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

1回答

13327閲覧

Springboot でCSVをダウンロードしたいが、出す項目を都度変えたい

tohmey

総合スコア10

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

0グッド

1クリップ

投稿2019/11/11 07:56

編集2019/11/12 04:45

前提・実現したいこと

参考文献によると、ENTITYリストだけあればサクッとCSVがダウンロードできる。
これを実装した時は本当に感動しました。
ですが、
CsvMapperもCsvSchemaも使うのが初めてで、うまくカスタマイズできないでいます。

やりたいことは、
ENTITYに項目A、項目B、項目C、項目Dとあるとして、
今回は項目A、項目BだけのCSVをダウンロードしたい。
今回は項目A、項目C、項目DのCSVをダウンロードしたい。
といったことです。

ENTITYに関して、固定でCSVへの除外項目を設定する方法は見かけました。
でも、可変でというものが見つからないです。

全項目出力する場合のコード

【Controller】画面から"csvDL"でポチっと呼ばれてるだけ

java

1@RestController 2public class CsvDLController { 3 @RequestMapping(value = "csvDL", method = RequestMethod.POST) 4 public ResponseEntity<byte[]> download() { 5 return service.downloadCsv(); 6 } 7}

【Service】fieldsは項目を絞るためのもの(現時点では使っていない⇒使いたい)

java

1@Service 2@Transactional 3public class CsvDLService { 4 public ResponseEntity<byte[]> downloadCsv() { 5 List<String> fields = dao.colmuns(); 6 fields.remove("除外フィールド1"); 7 fields.remove("除外フィールド2"); 8 9 return csvUtil.dlCsv(dao.selectAll(), fields); 10 } 11}

【postgresql】dao.colmuns で呼んでるSQL (dao.selectAllは単純な全件検索なので割愛)

sql

1SELECT 2 colmuns.attname AS colmun 3FROM 4 pg_attribute AS colmuns 5INNER JOIN 6 pg_class AS tables 7 ON colmuns.attrelid = tables.oid 8WHERE 9 tables.relname = '出力テーブル' 10 and colmuns.attnum > 0 11order by colmuns.attnum

【Utility】レスポンスに乗せる処理(ほぼ参考文献のまま)

java

1@Component 2public class DownloadHelper { 3 private static final String CONTENT_DISPOSITION_FORMAT 4 = "attachment; filename=\"%s\"; filename*=UTF-8''%s"; 5 6 public void addContentDisposition(HttpHeaders headers, String fileName) 7 throws UnsupportedEncodingException { 8 String headerValue = String.format(CONTENT_DISPOSITION_FORMAT, 9 fileName, UriUtils.encode(fileName, StandardCharsets.UTF_8.name())); 10 headers.add(HttpHeaders.CONTENT_DISPOSITION, headerValue); 11 } 12 13 public ResponseEntity<byte[]> fileDL(String lines, String fileName, String enc) throws Exception { 14 HttpHeaders headers = new HttpHeaders(); 15 addContentDisposition(headers, fileName); 16 return new ResponseEntity<>(lines.getBytes(enc), headers, HttpStatus.OK); 17 } 18}

【Utility】エンティティリストからCSVを作る(引数cols以外は、ほぼ参考文献のまま)※colsは使っていない

java

1public class CsvUtil { 2 @Autowired 3 DownloadHelper dlHelper; 4 5 public ResponseEntity<byte[]> dlCsv(List<?> entityList, List<String> cols) { 6 try { 7 // CsvMapperの設定 8 CsvMapper mapper = new CsvMapper(); 9 // 文字列にダブルクオートをつける 10 mapper.configure(CsvGenerator.Feature.ALWAYS_QUOTE_STRINGS, true); 11 // CsvSchemaの設定(ヘッダをつける) 12 CsvSchema schema = mapper.schemaFor(entityList.get(0).getClass()).withHeader(); 13 14 return dlHelper.fileDL(mapper.writer(schema).writeValueAsString(entityList), 15 entityToFilename(entityList.get(0), ".csv"), "UTF-8"); 16 17 } catch(Exception e) { 18 log.error("csv出力失敗"); 19 e.printStackTrace(); 20 return new ResponseEntity<>("error end".getBytes(), HttpStatus.OK); 21 } 22 } 23 24 public String entityToFilename(Object entity, String ext) { 25 String[] spl = entity.getClass().getName().split(Pattern.quote(".")); 26 return spl[spl.length-1].concat(ext); 27 } 28}

組み込みたいこと

【Utility】上記csvUtilの全項目CSVダウンロード機能に、項目絞込み(可変)を組み込みたい
⇒ getMethodsメソッドで、欲しい項目の分だけGETメソッドを抽出
⇒ toObjLstメソッドで、ENTITYオブジェクトから欲しい項目だけList<Object>に入れている
⇒ 引数のstgt は、"set" または "get" です

java

1 List<Object> objLine; 2 3 public Method[] getMethods (String[] fields, Class<?> entity, String stgt) { 4 Method[] methods = entity.getMethods(); 5 Method[] ret = new Method[fields.length]; 6 7 mss: for(Method m : methods) { 8 if (stgt.equals(m.getName().substring(0, 3))) { 9 for(int i = 0; i < fields.length; i++) { 10 if (fields[i].equals(StrUtil.camelToSnake(m.getName().substring(3)))) { 11 ret[i] = m; 12 continue mss; 13 } 14 } 15 } 16 } 17 return ret; 18 } 19 20 public List<List<Object>> toObjLst(String[] fields, List<?> recLst) throws Exception { 21 // エンティティリスト⇒オブジェクトリスト 22 List<List<Object>> lines = new ArrayList<List<Object>>(recLst.size()); 23 // 取り出したい項目のGETメソッド 24 final Method[] methods = getMethods (fields, recLst.get(0).getClass(), "get"); 25 26 recLst.forEach(rec -> { 27 objLine = new ArrayList<Object>(fields.length); 28 try { 29 for (Method m : methods) objLine.add(m.invoke(rec)); 30 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 31 e.printStackTrace(); 32 return; 33 } 34 lines.add(objLine); 35 }); 36 37 return lines; 38 }}

試したこと

最初に参考にしたサイト:Springboot でCSVをダウンロードしたい
その他、CsvMapperとCsvSchema、jacksonの使い方で検索しまくったが、欲しい答えが得られず。
これらについて解説されている文献(本でもOK)を教えていただけるだけでも助かります。

CSVを指定したフォルダに作る機能はすでに作ってあり、そこで使っている機能(組み込みたいこと)と組み合わせて、なんとかならないかと考えています。

できればCsvMapperやCsvSchemaを使って、できるだけ綺麗にやりたいことを実現したいですが、

response.setHeader("Content-Disposition","attachment;filename=""
+ URLEncoder.encode(filenm, "UTF-8") + """);
で、作成したファイルをダウンロードさせる方法でもいいです。
こちらも、いまひとつ使い方がわかりません。自分メモ:参考文献

補足情報(FW/ツールのバージョンなど)

spring、postgres、java 新しめだと思います…。あとで追加します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

レスポンスに
response.setHeader("Content-Disposition","attachment;filename=""

  • URLEncoder.encode(filenm, "UTF-8") + """);

を設定した上で、
レスポンスのOutputStreamにファイルの内容を一行ずつ書き込む。
ってことで、可変CSVのダウンロードはできるようになりました。
(ベタベタな感じです)

もっとキレイな書き方はできないか……。悩みます。

投稿2019/11/12 06:12

tohmey

総合スコア10

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問