32
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Djnagoメモ Content-Dispositionのfilenameに日本語をセットする

Last updated at Posted at 2017-03-07

2020/2/7 追記
同僚から指摘があり、以下の修正をしました :bow:

  • filename=の値もurl encodeする

##目的
リクエストに対してファイルを日本語ファイル名(マルチバイト文字列を含むファイル名)でダウンロードしたい。Djangoに限らずWebアプリ全般に共通のことです。

環境

Django: 1.10.xx
Python: 3系

Content-Diposition

httpでファイルをダウンロードするときはレスポンスのContent-Dispositionフィールドをセットする必要があります。ここでダウンロード時のファイル名や、すぐにダウンロードを実行するかなどを指定できます。

Content-Type='application/pdf'
Content-Disposition: filename="hogehoge.pdf";

DjangoのView

上記設定をDjangoのViewで行うとこのようになります。

肝は普通にファイル名をセットするのではなく、URLエンコーディングしたファイル名をセットしているというところです。
この設定でも行けるときは行ける気がしますが、ブラウザによっては文字化けします。

view.py
from django.views.generic import View
import urllib.parse

class DownloadTestView(View):
    def get(self, request):
        test_filename = 'test.pdf'
        response = HttpResponse(status=200, content_type='application/pdf')
        """
        〜なんかPDF生成処理する〜
        """
        response['Content-Disposition'] = "filename='{}'".format(urllib.parse.quote(test_filename))
        return response

解決策

ブラウザによって挙動が違うということは、ブラウザによって処理を変えろということですね。
httpリクエストのUser-Agentフィールドを見ればアクセスしてきたブラウザ名が分かるので、ブラウザごとのif文をに職人が真心込めて…

というようなことをしなくても、Content-Dipositionのfilename*フィールドをセットすることで対応可能のようです。

参考: ダウンロードファイル名、文字化けとの格闘

Content-Disposition = filename="ファイル名"; filename*=UTF-8''URLエンコーディングされたファイル名;

これでなんとかなりそうです。

結論

最終的にDjangoのviewに落とし込むとこんな感じです。

view.py
from django.views.generic import View
import urllib.parse

class DownloadTestView(View):
    def get(self, request):
        test_filename = 'test.pdf'
        quoted_filename = urllib.parse.quote(test_filename)

        # ついでに、RFC6266準拠しとく ("attachment" を追加)
        # https://tools.ietf.org/html/rfc6266#section-5
        response = HttpResponse(status=200, content_type='application/pdf')
        """
        〜なんかPDF生成処理する〜
        """
        response['Content-Disposition'] = "attachment;  filename='{}'; filename*=UTF-8''{}".format(quoted_filename, quoted_filename)
        return response

filename*にURLエンコードしたファイル名をセットすることで、各種ブラウザに対応できます。
Chrome、Firefox、Safariでは動作確認できました。

32
21
1

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
32
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?