C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

文字化けする画像ファイルヘッダー [1]

[トピック内 23 記事 (21 - 23 表示)]  << 0 | 1 >>

■88748 / inTopicNo.21)  Re[7]: 文字化けする画像ファイルヘッダー
  
□投稿者/ WebSurfer (1609回)-(2018/09/23(Sun) 12:24:22)
No88746 (魔界の仮面弁士 さん) に返信

> Fiddler をお使いなのであれば、恐らくは
> Inspectors - HexView タブで確認されたのだと思いますが、
> それだと Header 部に関しては化けてしまう可能性がありますので、

ご指摘の通り Fiddler の HexView から取得しました。

HexView は受信した生のバイト列ではなくて、それを何らかの方法で変換(デコード)した結果
のようです。

具体的にどのような操作を行っているかは不明ですが、結果から見ると変換の際 Shift_JIS は
デコードできず REPLACEMENT_CHARACTER に置き換えられたということだと思います。

ヘッダに Shift_JIS を混ぜて送ってくるなんて Fiddler にとっては想定外(Fiddler に限らず
一般的にも想定外?)ということなのかもしれませんね。

引用返信 編集キー/
■88749 / inTopicNo.22)  Re[5]: 文字化けする画像ファイルヘッダー
□投稿者/ 魔界の仮面弁士 (1858回)-(2018/09/23(Sun) 13:29:11)
No88733 (魔界の仮面弁士) に追記
>>さらに、RFC 6266 に準拠した設定がされているかもしれません。その場合 filename は以下の
>>ようになります。
>>filename*=utf-8''DSC_0063 - %e3%82%b3%e3%83%94%e3%83%bc%e5%8c%97%e5%9c%8b%e6%96%b0%e8%81%9e%e7%a4%be%e7%a4%be%e9%95%b7%e8%b3%9e.JPG
> 仕様上は " - " ではなく "%20-%20" だと思っていました。

.NET Framework 4.5 以降 (あるいは .NET Standard 1.1 以降) で追加されている
System.Net.Http.Headers.ContentDispositionHeaderValue クラスを使うことで、
Content-Disposition ヘッダーを簡単に処理することができました。


しかしながら、RFC 6266 / RFC 5987 に従った、正しいヘッダー記述が求められるようで、
filename*= で空白が "%20" になっていない場合や、
filename= の後に漢字等が含まれていた場合には、解析エラーとなります。


Dim head As System.Net.Http.Headers.ContentDispositionHeaderValue

'これは成功する
Dim value1 As String = "inline; filename*=utf-8''DSC_0063%20-%20%e3%82%b3%e3%83%94%e3%83%bc%e5%8c%97%e5%9c%8b%e6%96%b0%e8%81%9e%e7%a4%be%e7%a4%be%e9%95%b7%e8%b3%9e.JPG"
head = System.Net.Http.Headers.ContentDispositionHeaderValue.Parse(value1)
Console.WriteLine(head.FileNameStar)    '『DSC_0063 - コピー北國新聞社社長賞.JPG』
Console.WriteLine()

'これは解析エラーになる(System.FormatException)
Dim value2 As String = "inline; filename*=utf-8''DSC_0063 - %e3%82%b3%e3%83%94%e3%83%bc%e5%8c%97%e5%9c%8b%e6%96%b0%e8%81%9e%e7%a4%be%e7%a4%be%e9%95%b7%e8%b3%9e.JPG"
'head = System.Net.Http.Headers.ContentDispositionHeaderValue.Parse(value2)
'Console.WriteLine(head.FileNameStar)
Console.WriteLine()

'これは成功する
Dim value3 As String = "inline; filename=""DSC_0063 - COPY.JPG""; filename*=utf-8'ja-JP'DSC_0063%20-%20%e3%82%b3%e3%83%94%e3%83%bc%e5%8c%97%e5%9c%8b%e6%96%b0%e8%81%9e%e7%a4%be%e7%a4%be%e9%95%b7%e8%b3%9e.JPG"
head = System.Net.Http.Headers.ContentDispositionHeaderValue.Parse(value3)
Console.WriteLine(head.FileName)        '『"DSC_0063 - COPY.JPG"』
Console.WriteLine(head.FileNameStar)    '『DSC_0063 - コピー北國新聞社社長賞.JPG』
Console.WriteLine()


Internet Explorer 向けに、あえて "%20" ではなく " " を使っている実装も
まだまだ多そうなので(本来は RFC 違反)、そういうものにも対応させたいなら、
結局、自前で正規表現処理するしか無さそうです。



ただ、filename*= への対応は後回しにするとしても、
とにかく文字化けでも何とかしておきたいところ。

先の System.Net.Sockets.TcpClient 案は、低レベル API ゆえに
自前でレイヤを再実装しなければならないのが、やはりネックです。

https 通信時には SslStream を使う必要があったり、
サーバー側が 301 や 302 だったら、リダイレクトの処理を
加えたりしなければならず、汎用的な実装にするのは茨の道。


なのでできれば、System.Net.Http 名前空間のクラスなどで対処したいところ。

もしかして、System.Net.Http.HttpClient ならどうかな…と思ったんですが、
これも駄目でした。


Dim url As String = "http://cms1.ishikawa-c.ed.jp/~shough/NC2/htdocs/?action=common_download_main&upload_id=4537"
Using client As New HttpClient()
    Dim request As New HttpRequestMessage(HttpMethod.Head, url)
    Dim content As HttpContent = client.SendAsync(request).Result.Content

    '今回の不正な Content-disposition ヘッダーを処理できていない
    'Dim headers As HttpContentHeaders = content.Headers

    'rawBinary.Length = 0 になってしまう。
    'Dim rawBinary As Byte() = content.ReadAsByteArrayAsync().Result

    'rawStream.Length = 0 になってしまう。
    'Dim rawStream As Stream = content.ReadAsStreamAsync().Result

    'String.Empty になってしまう。
    Dim rawString As String = content.ReadAsStringAsync().Result

    'そもそも、内部ストリームが既に閉じられている
    'Dim bf As BindingFlags = BindingFlags.GetField Or BindingFlags.Instance Or BindingFlags.NonPublic
    'Dim stm = DirectCast(GetType(StreamContent).InvokeMember("_content", bf, Type.DefaultBinder, content, Nothing), Stream)
    'Dim newStm As New MemoryStream()
    'stm.CopyTo(newStm)  '例外:ObjectDisposedException

End Using



あと思いつくのは、マネージライブラリから P/Invoke に切り替えて、
WinHttpQueryHeaders API を試してみるという手法ぐらいです。(未検証)

引用返信 編集キー/
■88752 / inTopicNo.23)  Re[6]: 文字化けする画像ファイルヘッダー
□投稿者/ 魔界の仮面弁士 (1859回)-(2018/09/24(Mon) 04:37:52)
No88749 (魔界の仮面弁士) に追記
> あと思いつくのは、マネージライブラリから P/Invoke に切り替えて、
> WinHttpQueryHeaders API を試してみるという手法ぐらいです。(未検証)


Windows 10 (April 2018 Update以降) に含まれる『cURL コマンド』を
下記のように指定して使うことで、ヘッダーの生のバイナリを得る事が出来ました。

curl.exe "http://cms1.ishikawa-c.ed.jp/~shough/NC2/htdocs/?action=common_download_main&upload_id=4537" -I


ということで、Process クラスで curl コマンドを呼び出す方向で組み上げてみました。

コードが長くなってしまい掲示板に書ききれないので、下記にソースを置いておきます。
http://www.vb-user.net/junk/replySamples/2018.09.22.19.00/Module1.txt


どの Encoding を使えば文字化けしないのかは、事前に確認できないので、
ISO-8859-1、iso-2022-jp、Shift_JIS、UTF-8、euc-jp を順に試してみて、
変換エラーにならなかった場合にのみ、ファイル名を解析するようにしています。
引用返信 編集キー/

このトピックをツリーで一括表示

<前の20件
トピック内ページ移動 / << 0 | 1 >>

このトピックに書きこむ