jQuery、Node.jsを使ってプログラムでファイルダウンロードを実装する

以下を実現する方法のメモ

  1. jQueryでformを動的作成してsubmitする
  2. Node.jsで、リクエストされたファイル名に該当するファイルを開き内容をレスポンスに書き込む
  3. ブラウザ標準のファイルダウンロード処理に移行させる

当初は$.postを使ってどうにかしようと思ったが、レスポンスが非同期で返却されるものをブラウザ標準のダウンロード処理に移行させる方法がなく断念。

ブラウザのファイルダウンロードを実行させるためには、 非同期でjavascriptで処理するのでなく、どうにかして画面遷移相当のイベントを発生させないと反応しない。

仕方がないので、jQueryで動的にformを作成し、ダウンロードしたいファイル名を送信することで、 クライアント側は対応した。ポイントは$.postではなく、form.submit()するところにある。

$('.btn_download').click(function (e) {
   
  // ダウンロードファイル名 ( 実際にはどこからか取得する )
  var select_file = "sample.zip";
   
  // 動的にformを作成して、select_file="sample.zip"をsubmitする
  // 送信先は
  var form = $("<form>").append(
    $("<input>").attr("type","hidden")
      .attr("name", "select_file")
      .attr("value", JSON.stringify({"select_file" : select_file}) )
  ).attr( { "action":"/download", "method":"post" })
  .css({"display":"none"});
   
  // bodyに追加して、submit
  $("body").prepend(form);
  form.submit();
   
  return false;
});

クライアント側からは直接参照できない場所にあるファイルをダウンロードする想定で、Node.js側の処理は、submitで送信された情報をreq.bodyから取得する。

所定の場所にあるファイルサイズを取得し、res.writeHead()でレスポンスヘッダを作成するファイルをfs.createReadStream()でストリームを読み込んで、レスポンスとpipe()で紐付ける。