0
0

More than 1 year has passed since last update.

【Flutter】Webでcsvファイルをダウンロードする

Last updated at Posted at 2022-12-15

はじめに

よくあるWebページからcsvをダウンロードする機能ですが、この記事はFlutterを用いてcsvダウンロード機能とnodejsを用いてawsのWebAPIに実装について書いています。

Flutter Webからダウンロード

AnchorElementクラス

使うSDKはdart:htmlライブラリAnchorElementクラスです。

実装

BOM

エンコードしたファイルの先頭にBOMを設定しないと文字化けすることがあります。

バイト順マーク (バイトじゅんマーク、英: byte order mark) あるいはバイトオーダーマークとは、通称BOM(ボム)といわれるUnicodeの符号化形式で符号化したテキストの先頭につける数バイトのデータのことである。このデータを元にUnicodeで符号化されていることおよび符号化の種類の判別に使用する。

バイト順マーク - Wikipedia

各符号化形式(符号化スキーム)ごとのバイト順マーク

UTF-8の場合、BOMは下記です。

 List<int> excelCsvBytes = [0xEF, 0xBB, 0xBF]

CSV SDK

CSVの整形は下記のSKDを使うと便利です。
https://pub.dev/packages/csv

dependencies:
  csv: ^5.0.1

実装例

  • ModelmからCSVファイルをダウンロード
import 'package:csv/csv.dart';
import 'dart:html';
import 'dart:convert';
// csvデータ
List<List> users = [["姓", "名", "性別"], ["テスト", "太郎", "男"]];
// SDKによるCSVデータ整形
String csvString = const ListToCsvConverter().convert(users);
// utf-8バイト変換
List<int> excelCsvBytes = [0xEF, 0xBB, 0xBF, ...utf8.encode(csvString)];
// base64エンコード変換
String base64ExcelCsvBytes = base64Encode(excelCsvBytes);
// CSVダウンロード
AnchorElement(href: 'data:text/plain;charset=utf-8;base64,$base64ExcelCsvBytes')
    ..setAttribute('download', 'user.csv')
    ..click();
  • APIリスポンスからデータをダウンロード
// データリクエスト省略
...
// APIResponseからデータを受け取るときはresponse.bodyBytesで受け取る
// base64エンコード変換
String base64ExcelCsvBytes = base64Encode(response.bodyBytes);
// CSVダウンロード
AnchorElement(href: 'data:text/plain;charset=utf-8;base64,$base64ExcelCsvBytes')
    ..setAttribute('download', 'user.csv')
    ..click();

NodejsによるWebAPIのCSVデータダウンロード

SDK

package.json

{
    "dependencies": {
        "csv": "^6.0.4"
    }
}

実装

csvデータを作成する関数をWrapする

const CSV = require('csv')

function createCsvData(data) {
  return new Promise(resolve => {
    CSV.stringify(data, { bom: true, quoted: true, header: true }, (error, csvData) => {
      resolve(csvData)
    })
  })
}

ダミーデータ

const rows = [
    {
       "": "テスト",
       "": "太郎",
       "性別": "", 
    }
]
const csv = await createCsvData(rows)

リスポンスでデータを送信する

res.setHeader('Content-disposition', `attachment; filename=user.csv`)
res.setHeader('Content-Type', 'text/plain')
res.send(csv)

参考

0
0
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
0
0