Content-Disposition の日本語問題

  • 13
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

たとえば rails で、

send_file(filename: "日本語.pdf")

のように日本語指定するとブラウザによってうまくいかない場合がある。
この問題は検索してみるとなかなかやっかいなのだが、いちおう現時点では
http://greenbytes.de/tech/tc2231/#attwithfn2231utf8
これがファイナルアンサーと思われる。

しかし rails3.2 rails4.0 時点での send_file は、この記法

Content-Disposition: attachment; filename*=UTF-8''foo-%c3%a4-%e2%82%ac.html

に対応していない。(see rfc2231)

そこでモンキーパッチを当てよう。

config/initializers/send_file_with_utf8.rb
module ActionController
  module DataStreaming
    def send_file_headers_with_utf8!(options)
      send_file_headers_without_utf8!(options)
      match = /(.+); filename="(.+)"/.match(headers['Content-Disposition'])
      encoded = URI.encode_www_form_component(match[2])
      headers['Content-Disposition'] = "#{match[1]}; filename*=UTF-8''#{encoded}" unless encoded == match[2]
    end
    alias_method_chain :send_file_headers!, :utf8
  end
end

一発パッチコマンドはこちら↓

wget https://gist.github.com/kuboon/5494463/raw/31d80be6dc23eac2bc05d996df1e0293ae001124/send_file_with_utf8.rb -P config/initializers/

update: 2013/05/01 Windows版 safari ではうまくいかないことが判明した。

Content-Disposition をどんなに工夫しても無視され、URL の末尾のファイル名が使用されるっぽい。そこで、まず filename をオプショナルに受け取れるように routes.rb を修正

config/routes.rb
  get "/pdf/:id(/:filename)" => "pdfs#show"

action に以下のように、自分自身にリダイレクトするコードを書く。(gem 'useragent' を使用)

  user_agent = UserAgent.parse(request.env['HTTP_USER_AGENT'])
  if params[:filename].nil? && user_agent.browser == "Safari" && user_agent.platform == "Windows" 
    # && user_agent.version <= "5.1.7" 新バージョンで修正されたら uncomment
    return redirect_to pdf_path(params[:id], filename)
  end

さすがにこの処理をモンキーパッチで書くのは黒魔法過ぎるのでここで妥協。