
【JavaScript入門】画面遷移しないでファイルをサーバーに送信する(sendArea.js)
sendArea.js
は 「投稿する」ボタンを押した瞬間に画像バイナリ + コメント文字列を Ajax でサーバへ送信 し、ページ遷移なしでタイムライン (postListArea
) を即時リロードするモジュールです。画像は <canvas>
上の内容を PNG Blob に変換、コメントはテキストで FormData
に詰めます。送信完了後は成功トーストを表示し、投稿一覧を updatePostList()
(別モジュール)で再取得するだけなので UX が途切れません。

フォルダ構成(該当部分)
node-js/
└─ app/
├─ index.html
├─ style.css
└─ js/
├─ common.js
├─ storage.js
├─ imageArea.js
├─ imageEffects.js
├─ controlArea.js
├─ commentArea.js
├─ sendArea.js ← ★今回実装
├─ dateFormat.js
└─ postListArea.js
sendArea.js ― フルコード & 詳細コメント
/* ---------------------------------------------------
sendArea.js
- 画像 + コメント をサーバーへ POST
- 完了後タイムラインを更新
--------------------------------------------------- */
window.addEventListener('DOMContentLoaded', () => {
/* === 対象 DOM === */
const btnSend = document.querySelector('#send'); // 投稿ボタン
const txtArea = document.querySelector('#comment'); // コメント欄
const canvas = document.querySelector('#view'); // プレビューキャンバス
/* === クリックで非同期送信 === */
btnSend.addEventListener('click', async () => {
/* ---------- 1. 入力バリデーション ---------- */
const comment = txtArea.value;
const lenMax = parseInt(txtArea.dataset.lenmax, 10);
// 文字数チェック
if (comment.length > lenMax){
alert(`コメントが ${comment.length} 文字です。\n最大 ${lenMax} 文字を超えています。`);
return;
}
// 画像チェック
if (!canvas.getAttribute('time')){
alert('画像が読み込まれていません。');
return;
}
/* ---------- 2. Canvas → PNG Blob 変換 ---------- */
// Canvas を Base64 → バイナリ配列 → Blob へ
const base64 = canvas.toDataURL('image/png').split(',')[1];
const bin = atob(base64); // Base64 → binary string
const buf = new Uint8Array(bin.length);
for (let i = 0; i < bin.length; i++) buf[i] = bin.charCodeAt(i);
const blob = new Blob([buf.buffer], {type: 'image/png'});
/* ---------- 3. FormData に詰めて送信 ---------- */
const fd = new FormData();
fd.append('comment', comment);
fd.append('image', blob); // `<input type=file>` 相当
try{
const res = await fetch('/post', {method:'POST', body: fd});
if (!res.ok) throw res; // ステータス 2xx 以外は例外
await res.text(); // サーバ応答 (ここでは文字列想定)
updatePostList(); // 🎉 タイムラインを再取得
alert('投稿が完了しました!');
}catch(err){
alert('投稿に失敗しました。サーバーを確認してください。');
console.error(err);
}
});
});
主要 API/命令まとめ
API / プロパティ | 働き | 用途/ポイント |
---|---|---|
canvas.toDataURL('image/png') | Canvas → Base64 PNG | クライアント側で画像データ取得 |
atob() / Uint8Array | Base64 → バイナリ配列 | PNG Blob を生成する前処理 |
new Blob([...], {type}) | バイト列 → Blob | MIME "image/png" を指定 |
URL.createObjectURL(blob) | Blob → 一時 URL | 今回は直接送信なので未使用 |
FormData.append(key,val) | マルチパートボディに追加 | ファイルも文字列も同列に扱える |
fetch(url,{method:'POST',body:fd}) | Ajax POST | ページ遷移せず送信 |
updatePostList() | タイムライン再描画 | postListArea.js が提供 |
関数・処理フロー解説
処理段階 | 主な関数/行 | 詳細 |
---|---|---|
1. バリデーション | if (comment.length > lenMax)… | 上限超過コメントや画像未読込を即時ブロック |
2. 画像変換 | canvas.toDataURL() → atob() | クライアント JS だけで Canvas を PNG Blob 化 |
3. 送信 | FormData + fetch | multipart/form-data 形式で /post エンドポイントへ |
4. 成功ハンドラ | updatePostList() | 投稿完了後に一覧を Ajax 再取得して “瞬時に反映” |
エラーハンドラ | catch(err) | ネットワーク/サーバ障害をアラート表示&ログ出力 |
実装ポイント & ベストプラクティス
- Base64 → Blob
canvas.toBlob()
を使うと非同期 API で簡潔に書けますが、Edge 古い版など対応外のブラウザもあるためここでは 手動変換 を示しています。モダン環境のみを想定する場合はcanvas.toBlob()
が簡単です。 - multipart/form-data
ファイルとテキストを一緒に送りたい場合はFormData
を必ず使用。Content-Type
ヘッダーは fetch が自動付与 するので自分で指定しない。 - updatePostList() の分離
投稿完了後の UI 更新はpostListArea.js
に切り出し、責務を明確化。テストや再利用が楽になります。 - 適切なエラーメッセージ
res.ok
のチェックを忘れると 500 などでも成功扱いになるので要注意。 catch ではログを出してデバッグしやすく。
これで ページリロードなしの投稿 機能が完成しました。
次回は、 過去投稿のタイムライン表示 & いいね!ボタンのリアルタイム更新 を実装する postListArea.js
を解説していきます。