俺のダウンロードファイル名がこんなに文字化けするはずがない 〜 Windows/IEでの日本語ダウンロードファイル名の文字化けに対処する。Zip対応、Railsの場合。

[追記:2014-08-20]

ここに書いたノウハウをGem化しました。

Rails の send_file や send_data でのファイル名文字化けを手軽に解消! ungarbled gemをリリースしました。

[/追記]

Windows/IEの日本語ダウンロードファイル名の文字化け、現状はこのやり方で対応できるはず(RailsのController)。ブラウザ、OSの判定にbrowser gem を使ってます。

通常ファイル名

def encode_filename(filename)
  if browser.ie? # IEの場合はURLエンコードする
    ERB::Util.url_encode(filename)
  else
    filename
  end
end

send_file('path/to/file', # ファイルのパス
          filename: encode_filename('日本語ファイル名.txt'), # ここで文字化けを防ぐ
          disposition: 'attachment'
         )
参考

Zipの中のファイル名

def encode_filename_for_zip_item(filename)
  # Windows8未満はZip中のUnicodeファイル名に対応してないのでcp932をつかう。
  # 8はcp932のエンコードに対応してないので気をつける!
  if browser.windows? && !browser.windows8?
    filename.encode('cp932', invalid: :replace) # Ruby1.9以上
  else
    filename
  end
end

# rubyzipの例
directory = '/path/to/include/in/zip/' # 日本語ファイル名のファイルを含んだZipアーカイブするディレクトリ
zipfile_name = '/path/to/output/zip_file.zip' # サーバ上のZipアーカイブの出力ファイル名

Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
  Dir[File.join(directory, '**', '**')].each do |file|
    # Windows7以下で、Zipアーカイブの中のファイル名の文字化けを防ぐ
    zipfile.add(encode_filename_for_zip_item(file.sub(directory, '')),
                file
               )
  end
end

send_file(zipfile_name,
          filename: encode_filename('日本語ファイル名.zip'),
          disposition: 'attachment'
         )
参考

・・・タイトル長っ