LoginSignup
3
4

More than 3 years have passed since last update.

Express.jsでファイルダウンロード

Posted at

Express.jsで画像などのファイルをダウンロードする方法です。
本記事の内容は以下のドキュメントに書かれている内容の説明になります。
https://expressjs.com/ja/api.html

実行環境

express.js 4.17.1
MacOS 10.15.7

方法その1 簡易的な方法

import express from 'express';

export const router: express.Router = express.Router()

router.get('/download', (req, res) => {
  res.download('images/どね.jpg')
})

downloadメソッドを使います。ファイルパスを引数に取ることになるので、一度ファイルをストレージのどこかに置く必要があります。すでにBuffer形式になっている場合は少し面倒ですね。

方法その2 headerに指定

import express from 'express';
import fs from 'fs/promises'

export const router: express.Router = express.Router()

router.get('/set', async (req, res) => {
  const img = await fs.readFile('images/どね.jpg')
  const fileName = encodeURIComponent('どね.jpg')
  res.set({'Content-Disposition': `attachment; filename=${fileName}`})
  res.status(200).send(img)
})

レスポンスのヘッダーを直接指定します。Content-Dispositionattachmentを指定することでブラウザ側でダウンロードファイルであることを認識してくれます。
それ以外にも以下の処理が必要になります。

  • Bufferファイルを一度読み込んでbodyに入れる
  • 日本語ファイル名の可能性がある場合はファイル名にエンコードをかける

filenameとfilename*の違いについて

引数の filename と filename* の違いは、 filename* が RFC 5987 で定義されているエンコーディングを使用するという点のみです。単一のヘッダーフィールドの値に filename と filename* の両方が存在する場合は、両方が解釈できる場合、 filename* が filename よりも優先されます。

方法1ではfilename*が自動で使われて、方法2ではどちらも指定できます。

方法1 方法2
image.png image.png

いくつかのブラウザで試しましたがすべてfilename*を認識できていました。使える文字もこちらのほうが多いようです。あえてfilenameを使う必要はなさそうです。もし使えないブラウザがあったら教えていただきたいです。

試したブラウザを以下に置いておきます。

ブラウザ バージョン 対応状況
Chrome 88
FireFox 88
Microsoft Edge 88
Internet Explorer 11

まとめ

たいていはフレームワークに乗っかった方が後々困ることもないので方法1推奨です。
修正がかかったらフレームワーク側を直せば良い話ですし。

3
4
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
3
4