ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
Ajax を使わない場合
<a href="/api/export.csv?from=2026-09-01">CSV をダウンロード</a>
// JavaScript から遷移させる場合
location.href = "/api/export.csv?from=2026-09-01";
サーバーが Content-Disposition: attachment を返せば、それだけでダウンロードになります。認証が Cookie で、条件が URL に載せられるなら、この方法が最も簡単で確実です。
Ajax が必要になるのは次の場合です。
- POST で大量の条件を送る必要がある
Authorizationヘッダーなど、リンクでは付けられない情報が要る- 生成中にローディング表示を出したい
- 失敗したときに画面遷移せずエラーを表示したい
jQuery Ajax で受け取って保存する
function downloadCsv(params) {
$.ajax({
url: "/api/export",
type: "POST",
data: JSON.stringify(params),
contentType: "application/json",
// 既定では文字列として扱われ、バイナリが壊れる
xhrFields: { responseType: "blob" },
})
.done(function (blob, status, xhr) {
// ファイル名はサーバーのヘッダーから取る
const disposition = xhr.getResponseHeader("Content-Disposition") || "";
const m = /filename\*?=(?:UTF-8'')?"?([^";]+)"?/i.exec(disposition);
const filename = m ? decodeURIComponent(m[1]) : "export.csv";
saveBlob(blob, filename);
})
.fail(function (xhr) {
alert("ダウンロードに失敗しました: " + xhr.status);
});
}
function saveBlob(blob, filename) {
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url); // 解放しないとメモリに残り続ける
}
xhrFields: { responseType: "blob" } を忘れると、jQuery が受信データを文字列として解釈します。ZIP や Excel のようなバイナリは、この時点で壊れて開けなくなります。
fetch で書く場合
async function downloadCsv(params) {
const res = await fetch("/api/export", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(params),
});
if (!res.ok) {
throw new Error(`HTTP ${res.status}`);
}
const blob = await res.blob();
saveBlob(blob, "export.csv");
}
新規に書くなら fetch のほうが簡潔です。jQuery を使っているプロジェクトでも、この部分だけ fetch にして構いません。
ブラウザ側で CSV を作る
function toCsv(rows, headers) {
const escape = (v) => {
const s = v == null ? "" : String(v);
// ダブルクォート・カンマ・改行を含むなら囲む。中の " は "" にする
return /["\r\n,]/.test(s) ? `"${s.replaceAll('"', '""')}"` : s;
};
const lines = [
headers.map(escape).join(","),
...rows.map((row) => headers.map((h) => escape(row[h])).join(",")),
];
return lines.join("\r\n"); // Excel 向けは CRLF
}
const rows = [
{ id: 1, name: "田中, 太郎", note: '改行\nあり' },
{ id: 2, name: "鈴木", note: '"引用" あり' },
];
const csv = toCsv(rows, ["id", "name", "note"]);
const blob = new Blob(["\uFEFF" + csv], { type: "text/csv;charset=utf-8" });
saveBlob(blob, "users.csv");
エスケープの規則(RFC 4180)
| 値に含まれるもの | 処理 |
|---|---|
| カンマ・改行・ダブルクォート | 値全体を " で囲む |
| ダブルクォート | さらに "" に二重化する |
先頭が = + - @ | Excel が数式として実行する。先頭に ' を付けるなどして無害化する |
最後の項目はCSV インジェクションと呼ばれる問題です。利用者が入力した値をそのまま CSV に出すと、開いた人の環境で任意のコマンドが動く恐れがあります。
Excel で文字化けさせない
// BOM 無し: Excel が Shift_JIS と誤認して日本語が化ける
new Blob([csv], { type: "text/csv" });
// BOM 付き: UTF-8 として認識される
new Blob(["\uFEFF" + csv], { type: "text/csv;charset=utf-8" });
\uFEFF は1 文字の BOMです。Blob が UTF-8 で符号化するときに EF BB BF の 3 バイトになります。
サーバー側で BOM を付けている場合、ここでさらに付けると二重になり、1 列目のヘッダー名がずれます。どちらで付けるかを決めてください。
ファイル名の指定
Content-Disposition: attachment; filename="export.csv"; filename*=UTF-8''%E5%A3%B2%E4%B8%8A.csv
日本語のファイル名は filename*=UTF-8'' の形(RFC 5987)で送ります。Ajax で受け取る場合、このヘッダーを JavaScript から読むには CORS の設定が要ります。
Access-Control-Expose-Headers: Content-Disposition
同一オリジンなら不要ですが、API を別ドメインに置いている場合はこれが無いと getResponseHeader() が null を返します。a.download にクライアント側で決めた名前を入れる方法でも構いません。
うまくいかないとき
| 症状 | 原因 |
|---|---|
| ファイルが壊れて開けない | responseType: "blob" の指定漏れ |
| 日本語が化ける | BOM が無い/二重に付いている |
| ダウンロードが始まらない | a.click() がユーザー操作の延長で呼ばれていない |
ファイル名が download になる | a.download が空。別オリジンだと無視される |
| ヘッダーが読めない | Access-Control-Expose-Headers が無い |
| 大きいファイルでタブが落ちる | Blob をすべてメモリに載せている。サーバー直リンクに切り替える |
| Excel で列がずれる | 値の中のカンマや改行をエスケープしていない |
非同期処理の中で a.click() を呼ぶと、ブラウザが「利用者の操作ではない」と判断してポップアップブロックの対象になることがあります。クリックから await を挟んで時間が空く場合は、進捗表示と再試行ボタンを用意しておくと確実です。
関連
- Ajax — 親カテゴリ
- $.ajax()
- 非同期処理
- Access to XMLHttpRequest at 'url1' from origin 'url2' has been blocked
- 配列からJSONに変換
- よくある事例
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページはありません
- $.ajax()
- CSVファイルのダウンロード
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- 【django】ログイン 認証機能 2026-09-08 03:22:09
- MySQL ERROR 1063 Incorrect column specifier for column|原因と直し方 2026-09-08 03:11:09
- 【PHPエラー】Object of class stdClass could not be converted to string 2026-09-07 07:46:04
- Julia Genie ローカル開発サーバ起動完全ガイド 2026-09-07 07:46:04
- Linuxで複数ファイルの文字列を一括置換|find・sed・xargsの安全手順 2026-09-07 07:45:13
- Laravel 記事一覧55件|環境構築・ルーティング・DB・エラー対処 2026-09-07 07:45:13
- JPEG(.jpg/.jpeg)画像形式の完全ガイド — 仕様・マジックナンバー・他形式との比較・EXIF 2026-09-07 07:45:13
- Javaの定数 2026-09-07 07:45:13
- hostnameコマンドの使い方|Windows・Linux・macOSでホスト名確認 2026-09-07 07:45:13
- NetBeansでTomcatを起動する手順|サーバ登録・ポート・トラブル対処 2026-09-07 07:45:13
- Laravelルートグループ|prefix・middleware・nameで一括管理 2026-09-07 07:45:13
- Oracle DROP USERでユーザー削除|CASCADE・接続中ユーザーの対処 2026-09-07 07:45:13
- SQLとは|DDL・DMLとリレーショナルデータベース操作の基本 2026-09-07 07:45:13
- Linux whichコマンドの使い方|絶対パス取得とtype・command -vの違い 2026-09-07 07:45:13
- Spring Framework 記事一覧31件|DI・設定・例外の対処 2026-09-07 07:45:13
コメントを削除してもよろしいでしょうか?