QA@IT
この質問・回答は、@ITの旧掲示板からインポートされたものです。

ファイルのダウンロードで日本語のファイル名が文字化けする問題

既に過去のスレッドで何度も議論されているこの話題ですが、
今回新しい発見があったので蒸し返してみました。

ちなみに、期待を込めて最後まで読む気になってくれた方のために
あらかじめ言っておくと、あくまで新しい発見があっただけで
問題解決してないです念のため。

私の調べた限りASP.NETに関しては、
HttpUtility.UrlEncode()を使うと[保存]に関してはOK。
しかし[開く]だとデコード前のファイル名で開いてしまう、
これに対する解決策はまだ出ていない、という状態かと。
(間違ってたらすみません)

ところが、最近たまたま社内のWebページで、
[開く]でも文字化けしないページを発見してしまいました。
(全角文字[1].xlsみたいに一時ファイル故の付加文字はありますが)
servletとjsp使ってるみたいですが、
社内ページといっても社内で開発してるわけじゃないので、
Webサーバに何使ってるかとかはわかりません。
同じ理由で開発元にどうやってんの?って聞くわけにもいかず、
とりあえずレスポンスヘッダを解析してみました(いいのか?w)

なお、今回試したファイル名は"全角文字.xls"です。
あとブラウザはIE6.0SP1で、解析にはetherealを使いました。
以下、関係ありそうなとこだけ抜粋です。

Server: Microsoft-IIS/5.0
Cache-Control: no-cache
Content-Type: application/vnd.ms-excel;charset=Windows-31J
Content-Disposition: attachment; filename=<問題の箇所>
Via: 1.1 - (DeleGate/7.5.4)

さて、<問題の箇所>ですが、16進表示すると

91 53 8a 70 95 b6 8e 9a 8e 78 6c 73

どうやら932のコードがそのまんま入ってるようです。
これができれば[開く]でも日本語ファイル名が!
ってASP.NETではどう書けばこれが実現できるんだ?わからんorz

今回わかったのはここまででした。
誰か実現方法ご存知でしたらご教授願いますm(_ _)m

以下はオマケです。一応VB.NETで作ったWebアプリのヘッダも解析してみました。
開発環境はVisual Stdio 2003 + .NET Framework 1.1 SP1です。




Dim fileName As String = "全角文字.xls"
'最初はここをコメントアウト fileName = HttpUtility.UrlEncode(fileName)
Response.ContentType = "application/vnd.ms-excel"
Response.Charset = "Windows-31J"
Response.AppendHeader("Content-Disposition", "attachment; filename=" + fileName)
Response.WriteFile(strXlsFilePath)
Response.End()

Server: Microsoft-IIS/5.0
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Content-Disposition: attachment; filename=<問題の箇所>
Transfer-Encoding: chunked
Cache-Control: private
Content-Type: application/vnd.ms-excel; charset=Windows-31J

<問題の箇所>の16進表示
e5 85 a8 e8 a7 92 e6 96 87 e5 ad 97 2e 78 6c 73

utf-8になってました。

次に「最初はここをコメントアウト」を外すと、
<問題の箇所>の16進表示は以下のようになりました。

25 65 35 25 38 35 25 61 38 25 65 38 25-61 37 25
39 32 25 65 36 25 39 36 25 38 37 25 65-35 25 61
64 25 39 37 2e 78 6c 73

これはASCIIで%e5%85%a8%e8%a7%92%e6%96%87%e5%ad%97.xlsです。
まぁだいたい予想通りの結果でしたが、
Transfer-Encoding: chunked は勝手についちゃうんでしょうか?
以上、オマケでした。

質問者:ぼのぼの

回答

通りすがりの者ですが。

同様の問題が起こり、ググってたらこちらに辿り着き、
ご教示いただいた方法で対応することが出来ました。

謝意も兼ねて、
VB2005 + ASP.NET 2.0(.NET fx 2.0) + IIS5.1(WinXP)
の環境で出来たのでご報告させていただきます。

当方で試した限り、
当初はご提示の方法では文字化けは直りませんでした。
試行錯誤の結果、
ファイル名をシフトJISに変換しURLエンコードして
それを“download.asp”にリダイレクトする際にクエリ文字列に指定すれば文字化けしません。
具体的なコードは以下の通りです。

==任意のaspxコード内メソッドにて=================================================
Imports System.Text
Imports System.Web

Dim fileName As String = "全角文字.xls"
Dim sjisEnc As Encoding = Encoding.GetEncoding(932)
Dim bytesData As Byte() = Encoding.Convert(Encoding.UTF8, sjisEnc, Encoding.UTF8.GetBytes(fileName))
Dim sjisName As String = HttpUtility.UrlEncode(bytesData)
Response.Redirect("download.asp?filename=" & sjisName)

=====================================================================

以下のURLも参考になりました。
http://www.site-cooler.com/tips/asp_binarydownload.htm

投稿者:凡庸

編集 履歴 (0)

NAL-6295です。

ASP.NET2.0以降は

web.configのresponseHeaderEncodingをshift-jisに設定し、filename=(ここの部分はurlencodeしないでそのままの文字列)にすれば、文字化けしないようになったと記憶しています。
http://msdn2.microsoft.com/ja-jp/library/hy4kkhe0.aspx

投稿者:NAL-6295

編集 履歴 (0)

NAL-6295 様

ご提示の方法でできるようになりました。
さらに
普通に、ポストバック時のレスポンスで日本語名のファイルを
ファイル名の文字化け等無しにダウンロードできるようになりました。

大変助かりました。  

〆凡庸SE

投稿者:凡庸

編集 履歴 (0)

かなり時間を置いての自己レスですが、このスレ、結構色んなとこからリンク貼られてるようなので補足しておきます。
リンク元で、フリーのDLLを使わないと実装できないみたいな書かれ方をしていることがあるのですが、BASP21.DLLってのは巨大なユーティリティ関数群で、今回その中で使ってるのはBinaryRead()だけです。
要はASPは標準でバイナリファイルをバイト配列に読み込む関数を装備してないので、その部分はBASP21.DLLで補ってるわけですが、当然ながらバイナリファイル読込くらいなら簡単に作れます。サンプルコードは割愛。以下のURLを参考にすれば予想以上に簡単に作れると思いますよ
チュートリアル : Visual Basic .NET での COM オブジェクトの作成

投稿者:ぼのぼの

編集 履歴 (0)

ども、ぼのぼのです。自己レスですが、ついに解決しました!

最初はHttpResponseクラスを継承して、いじくりまわせれば…と考えていたのですが、
(というか誰かがそれをやってくれるのを密かに期待していた)
どうもHttpResponseクラスはそんな危険なことができるつくりにはなってないみたいで、
まぁ当然といえば当然なんでしょうけども(^^;
そもそも上に書いたことも、以前別の同内容のスレッドで紹介されていたここで
本家Microsoftが「できない」と公言していることなので、
やっぱ無理、というかできたとしても報われない作業量&危険度です。

で、じゃあASP.NETで無理ならASPとか使ったらどうなん?と思って、
だめもとで試してみたらうまくいってしまいました。
ただし、ASPはデフォルトでバイナリファイルの読み書きができないので、
実現するにはBASP21.DLLが必要です。
フリーのDLL使ってるわASP.NETじゃないわで
今のプロジェクトでこの方法が採用になるかはわかりませんが、
少なくとも私の環境では日本語のファイル名が[開く]でも文字化けせずに表示できました。
以下はサンプルコードです。

ASP.NET側(VB.NET)
------------------------------------------------------------------------
Dim fileName As String = "全角文字.xls"
Response.Redirect("download.asp?filename=" & fileName)
------------------------------------------------------------------------

download.asp
------------------------------------------------------------------------
<%
fileName = Request("filename")
filePath = Server.MapPath(fileName)
Set bobj = Server.CreateObject("basp21")
binData = bobj.BinaryRead(filePath)
Response.AddHeader "Content-Type", "application/vnd.ms-excel;charset=Windows-31J"
Response.AddHeader "Content-Disposition", "attachment; filename=" + fileName
Response.BinaryWrite binData
Response.End
%>
------------------------------------------------------------------------

投稿者:ぼのぼの

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。