📚

Golang Echo, Excelizeの出力をバイナリデータでHTTPリクエストのレスポンスとして返す

2022/10/12に公開

やりたいこと

  • Excelizeで.xlsxファイルの生成
  • ファイルとして保存せずにREST APIのレスポンスとして返す

どうやったか

ファイルを生成せずにHTTPリクエストのレスポンスに含めるには?という回答は以下のissueから回答を得ました。
WriteToBuffer() を使うことで、io.Readerとして bytes Bufferを受け取ることができます。
https://github.com/qax-os/excelize/issues/148

The execlize now support to get bytes.Buffer from the saved file by WriteToBuffer(), and we can get io.Reader

これをレスポンスと返す方法は以下の記事を参考にしました。他の実装例が見つからなかったのですごく助かりました。
https://kaminashi-developer.hatenablog.jp/entry/2020/12/17/093000

具体的な実装

実際に実装したものの抜粋です。抜けがあったらごめんなさい。

バックエンド側(Go Echo)の抜粋

func CreateExcel(c echo.Context) error {
	//excelファイル作成 具体的な内容は中略
	f := excelize.NewFile()

	buf, _ := f.WriteToBuffer()
	r = strings.NewReader(buf.String())
	//参考: https://github.com/qax-os/excelize/issues/127#issuecomment-435857445

	setResponse(c, r)

	return c.NoContent(http.StatusOK)
}

func setResponse(c echo.Context, body io.Reader) {
	encodeName := url.QueryEscape("book.xlsx")
	response := c.Response()
	response.Header().Set("Cache-Control", "no-store")
	response.Header().Set(echo.HeaderContentType, echo.MIMEOctetStream)
	response.Header().Set(echo.HeaderAccessControlExposeHeaders, "Content-Disposition")
	response.Header().Set(echo.HeaderContentDisposition, "attachment; filename="+encodeName)
	response.WriteHeader(200)

	io.Copy(response.Writer, body)
}

フロント側(axios) の実装部分

  return axios
    .get(`/url`, {
      responseType: 'blob',
    })
    .then((response) => {
      const filename = `book.xlsx` //フロント側でファイル名を決定
      const a = document.createElement('a')
      a.href = window.URL.createObjectURL(new Blob([response.data]))
      a.setAttribute('download', filename)
      a.click()
      a.remove()
    })

Discussion