ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|---|
クライアント側(JavaScript / fetch)
// モダンな書き方 (fetch + Blob)
async function downloadCsv() {
const response = await fetch("/api/users/export", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ filters: { status: "active" } })
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
// Blob として取得
const blob = await response.blob();
// ダウンロードリンクを作成して自動クリック
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "users.csv"; // ファイル名
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url); // メモリ解放
}
jQuery 版
// jQuery.ajax を使う場合
$.ajax({
url: "/api/users/export",
method: "GET",
xhrFields: { responseType: "blob" }, // ← Blob として受け取る
success: function(blob, status, xhr) {
// Content-Disposition からファイル名取得
let filename = "download.csv";
const cd = xhr.getResponseHeader("Content-Disposition");
const match = cd && cd.match(/filename="?(.+?)"?$/);
if (match) filename = decodeURIComponent(match[1]);
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
a.remove();
URL.revokeObjectURL(url);
},
error: function(xhr) {
alert("ダウンロード失敗: " + xhr.statusText);
}
});
サーバー側(Spring Boot)
@RestController
@RequestMapping("/api/users")
public class UserExportController {
private final UserService userService;
@GetMapping("/export")
public void exportCsv(HttpServletResponse response) throws IOException {
response.setContentType("text/csv; charset=UTF-8");
response.setHeader("Content-Disposition",
"attachment; filename=\"users.csv\"");
// BOM 付き UTF-8 (Excel 文字化け対策)
response.getOutputStream().write(new byte[]{(byte)0xEF, (byte)0xBB, (byte)0xBF});
try (PrintWriter writer = response.getWriter()) {
// ヘッダ行
writer.println("ID,氏名,メール,作成日");
// データ行 (ストリーミングで大量データ対応)
userService.streamAll().forEach(user -> {
writer.println(String.format("%d,%s,%s,%s",
user.getId(),
csvEscape(user.getName()),
csvEscape(user.getEmail()),
user.getCreatedAt()
));
});
}
}
// CSV エスケープ (カンマ・引用符・改行を含む値)
private String csvEscape(String value) {
if (value == null) return "";
if (value.contains(",") || value.contains("\"") || value.contains("\n")) {
return "\"" + value.replace("\"", "\"\"") + "\"";
}
return value;
}
}
サーバー側(PHP)
query("SELECT id, name, email, created_at FROM users");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
fputcsv($out, $row);
}
fclose($out);
exit;
サーバー側(Laravel)
public function export(): StreamedResponse
{
$headers = [
'Content-Type' => 'text/csv; charset=UTF-8',
'Content-Disposition' => 'attachment; filename="users.csv"',
];
return response()->stream(function () {
echo "\xEF\xBB\xBF"; // BOM
$out = fopen('php://output', 'w');
fputcsv($out, ['ID', '氏名', 'メール']);
User::chunk(1000, function ($users) use ($out) {
foreach ($users as $user) {
fputcsv($out, [$user->id, $user->name, $user->email]);
}
});
fclose($out);
}, 200, $headers);
}
サーバー側(Node.js / Express)
app.get("/api/users/export", async (req, res) => {
res.setHeader("Content-Type", "text/csv; charset=UTF-8");
res.setHeader("Content-Disposition", 'attachment; filename="users.csv"');
res.write("\uFEFF"); // BOM
res.write("ID,氏名,メール\n");
// ストリーミングで送る
const stream = db.users.find().stream();
stream.on("data", user => {
res.write(`${user.id},${csvEscape(user.name)},${user.email}\n`);
});
stream.on("end", () => res.end());
});
function csvEscape(s) {
if (s == null) return "";
if (/[,"\n]/.test(s)) return '"' + s.replace(/"/g, '""') + '"';
return s;
}
Excel 文字化け対策
Excel は BOM 付き UTF-8(バイトオーダーマーク EF BB BF)でないと、CSV を Shift_JIS と誤認して文字化けします:
# BOM の付与方法
# Java
out.write(new byte[]{(byte)0xEF, (byte)0xBB, (byte)0xBF});
# PHP
echo "\xEF\xBB\xBF";
# Node.js
res.write("\uFEFF");
# Python
csv_writer.writerow(["..."])
# ファイル open 時に encoding="utf-8-sig" を指定
CSV エスケープのルール
- 値に カンマ
,が含まれる → ダブルクォートで囲む - 値に 改行
\nが含まれる → ダブルクォートで囲む - 値に ダブルクォート
"が含まれる → ダブルクォート 2 個に置換、全体をダブルクォートで囲む
// 例
"Alice, Bob" → "Alice, Bob" # カンマ → 囲む
He said "Hi" → "He said ""Hi""" # " を "" にエスケープ
"Line1
Line2" → "Line1\nLine2" # 改行 → 囲む
大容量データのストリーミング
10 万行以上の CSV を全部メモリに溜めるとサーバが OOM します。ストリーミングで逐次送信:
- JPA:
@Query(... )+Stream+@Transactional(readOnly = true) - JdbcTemplate:
query(... , RowCallbackHandler) - Laravel:
chunk()やcursor() - Node:
cursor()/readable stream
関連記事
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページ
子ページはありません
同階層のページ
- インストール(eclipseプラグイン)
- クイックスタート
- プロジェクトの作成
- Spring Bootプロジェクトの作成
- Spring Bootプロジェクトの実行
- Spring BootでHello World!
- アノテーション一覧
- DB接続設定からエンティティおよびリポジトリの作成、値の取得まで(JPA編)
- DB接続設定や値の取得(JdbcTemplate編)
- ビューから値をモデルに格納しコントローラーで受け取る方法
- コントローラーにてモデルに値を格納してビューに渡す方法
- テンプレートエンジン
- ModelとModelAndViewの違い
- AOPの使用方法
- classpath: 内部ファイルの読み込み
- file: 外部ファイルの読み込み
- CSVファイルアップロード方法(Ajax)
- CSVファイルダウンロード方法(Ajax)
- Spring Bootプロジェクトのビルドと本番環境へのデプロイ方法(内部tomcat使用)
- Application.propertiesの環境依存設定の分割方法
- JPAにおけるEntityManagerの取得方法
- JPAにおけるjava.sql.Connectionの取得方法
- エラー一覧
- jarの引数を受け取る方法
- Spring BootでGmailからメール送信
- 複数のDBに接続する設定(Spring Boot & JPA編)
- ポート番号の変更
- Basic認証の実装と特定のURLに限定する方法
- Spring SecurityのBasic認証の無効化
- 独自のエラーページを定義する方法
- プロパティファイルの値やjar実行時の引数を取得する方法
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript base URL 取得方法|window.location.origin と SSR/Node.js 対応
- 4 YouTube Data API v3 エラー一覧|403/400/404 の主要原因と切り分け
- 5 Spring Frameworkのアノテーション一覧
- 6 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- Laravel キャッシュクリア完全ガイド(cache:clear / config:clear / 2026-05-18 07:42:07
- プロジェクトの作成と削除 2026-05-18 07:42:07
- インストール直後にNetbeansが反応しない 2026-05-18 07:42:07
- 動画やチャンネルの検索 2026-05-18 07:42:07
- APIキー取得方法 2026-05-18 07:42:07
- チャンネル情報の取得 2026-05-18 07:42:07
- API 入門 — Web API(REST / GraphQL / gRPC / 2026-05-18 07:42:07
- インストール(eclipseプラグイン) 2026-05-18 07:42:07
- Laravel「Dotenv values containing spaces must be surrounded 2026-05-18 07:42:07
- エラー一覧 2026-05-18 07:42:07
- curl: (51) SSL: certificate subject name '~' does not match 2026-05-18 07:42:07
- インストール方法(Windows版) 2026-05-18 07:42:07
- JSONから配列に変換 2026-05-18 07:42:07
- 処理を一定時間待つ 2026-05-18 07:42:07
- A non well formed numeric value encountered 2026-05-18 07:42:07
コメントを削除してもよろしいでしょうか?