search
LoginSignup
0

More than 1 year has passed since last update.

【Node.js】Expressとmulterを使って画像アップロードを実装する(multer, formData, axios)

はじめに

メインはフロントですが、趣味でExpressを触っている者です。フロント側で画像アップロードを行う際はFileAPIを使ってDataUrlを作ってからサーバーに送る。という流れになると思うのですが、Expressで実装するとなるといろいろ前提が違ってハマったのでメモします。

実装したコード

// 画像アップロード

app.post(
  '/photo/upload',
  // 解説①↓ ==========
  upload.any(), 
  // 解説①↑ ==========
  async (req: any, res: express.Response) => {
    // 解説②↓ ==========
    const customeId = 1
    const formData = new FormData()
    const file = req.files[0]
    formData.append('files[]', file.buffer, file.originalname)
    formData.append('customer_id', customeId)
    // 解説②↑ ==========
    try {
      const result = await axios({
        url: `< ここにAPIのURLを載せる >`,
        method: 'POST',
        // 解説③↓ ==========
        headers: {
          ...formData.getHeaders(),
          Authorization: req.headers.authorization,
          Accept: 'application/json',
        },
        // 解説③↑ ==========
        data: formData,
      })
      res.json({ ...result.data })
    } catch (error: any) {
      console.log(error.message, 'エラーが発生しています。')
    }
  }
)

解説①(multer)

upload.any(),

クライアント側から送られてきた画像情報を受け取るためにmulterを使います。multerを使わないとreq.dataの中に画像情報がないよー。という状況に陥ってしまいます。以下公式から引用。

Multer adds a body object and a file or files object to the request object. The body object contains the values of the text fields of the form, the file or files object contains the files uploaded via the form.

今回はFFB採用を想定してここからさらにバックエンドサーバーに送る想定なのでクライアントサーバー内にファイルを格納する必要はありません。そのため今回はupload.any()を使っています。

解説②(formData)

formData.append('files[]', file.buffer, file.originalname)

そもそもformタグに関しての認識が全然できていませんでした。例えばvue.jsを使ったらformタグを使わなくても入力内容をサーバーへ送れてしまうので、恥ずかしながらformタグの存在は知っていましたが、実際に使ったことがなかったため時間がかかってしまいました。反省です。formDataはformタグ内のinputでやっていることをサーバー側でやっているイメージです。

ポイント1(formDataで配列を送る)

filesは配列で[ 画像情報①, 画像情報②, 画像情報③, ]のように送りたいためfiles[]と記述しています。

key[]=value 形式の配列はサーバサイドでは [1,2,3] のような配列にパースされます。

とのことですが、はじめはfile.bufferの方に配列をつけていてエラーが止まりませんでした。こんな感じです。気をつけてください。

// これだとエラーになる
formData.append('files', [file.buffer], file.originalname)

ポイント2(formDataで第3引数を入れている理由)

form-dataは、入力クラス次第で、ファイル名などの情報を自動的に推測してくれるが、ファイルのメタ情報が失われている場合、form.appendの第三引数で明示的に指定する必要がある。

ということで通常のformDataの場合は第3引数に値を入れる必要はないのですが、引用内容ファイルを扱うときには気を付けなければいけません。

解説③(formData.getHeader)

headers: {
          ...formData.getHeaders(),
          Authorization: req.headers.authorization,
          Accept: 'application/json',
        },

getHeaderに関しては調べてば出てくる情報だと思うのですが、念のため。getHeders()はformdataのメソッドでcontent-typeを提供してくれます。authrizationなどのオプションも追加する場合は1階層下に設定しなくてはいけないのでスプレッド構文でcontent-typeだけオブジェクトから解放するようにしてください。

さいごに

multerに関してはもっと深掘りをする必要があると思いました。
また、画像のアップロードに関してはアプリケーションにとって必須の機能になるのでExpressではどのように実装するのか全体像を把握することができてよかったです。今まででログイン機能等のセキュリティ関連、そして今回の画像アップロードが理解でき簡単なCRODアプリならすぐに作れそうだなと自信がつきました。

参考URL

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
What you can do with signing up
0