2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

fastapi の FileResponse のファイルタイプ推定が動かなかった時のメモ。

Last updated at Posted at 2025-04-03

xlsx ファイルをレスポンスで返そうとした時に MIMETYPE が自動で設定されたりされなかったりした。
実行環境にエクセルが入っているかどうかで変わるっぽい。

背景

fastapi でファイルをダウンロードする API を作成した。
Content-Disposition ヘッダーを設定しておけばファイルレスポンスがいい感じになるので設定していたが、
テスト用サーバに上げるとうまく設定されない(text/plain になる)場合があったので調べた。

フロント側の処理を色々書いても解決できそうだが、 Content-Disposition ヘッダーを正しく使うのが良さそう。

fastapi の FileResponse

fastapi の FileResponse はファイルの MIMETYPE を推定してくれるが、xlsx とかで推定できないことがある。

from fastapi.responses import FileResponse

# res.media_type は 'text/csv' になる
res = FileResponse('test.csv')

# res.media_type が 'text/plain` になる場合がある
# `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` になって欲しい
res = FileResponse('test.xlsx')

基本的には FileResponse でレスポンスを作っておけば Content-Disposition ヘッダーもいい感じにしてくれる。
(type も推定されたものがセットされる)

今回推定できなかったのは xlsx
mac でローカル実行したときは推定できたが、 windows サーバに上げると推定できなかった。

解決策

media_type を明示的に指定する。

from fastapi.responses import FileResponse
res = FileResponse('test.xlsx', media_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')

自動で推定してくれるところはそのままにしたかったので、実際に使ったのは以下のような形。

from fastapi.responses import FileResponse
res = FileResonse('test.xlsx')

if res.media_type == 'text/plain':
    res = FileResponse('test.xlsx', media_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')

# インスタンス作成後に更新してもレスポンスに反映されなかった
# res.media_type = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'

インスタンス作成後にmedia_type を変更すると、インスタンスの更新は行われるが
レスポンスに反映されなかった。

原因

python の mimetype 推定は環境によって結果が異なる。

.txt, .csv などの一般的なものはデフォルトで設定されているが、その他の mimetype 情報は
システム環境から取ってきている模様。

筆者の macbook だと /etc/apache2/mime.types のデータが参照されていた。windows だとレジストリ情報から取ってくるらしい。

今回は windows サーバで xlsx の推定ができなかった。
エクセルを入れていなかったのでレジストリに情報がなかったのかもしれない。

from mimetypes import guess_type
guess_type('test.xlsx')

# 推定できるとき
# ('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', None)

# 推定できないとき
# (None, None)

参考サイト

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?