URLエンコード
HTTPプロトコルで使用されるURLは通常ドメイン名、パス、パラメータからなっています。通信の階層を考えると、URLはパケット内の単なるデータなので基本的にはなんでも送受信できます。しかし、ドメイン名は人が認識するための文字列で、IPアドレスに変換して使われます。どんな地域、コード系でも表示可能であるように7単位コードと決められているものと思います。
いろいろな文字コード系が使用されているわけですが、データ交換用符号は、0x7f 以下に同じ文字を割り当てています。0x7f以下のコードだけが使われていれば、sjisのファイルも、ASCIIのファイルも、UTF-8のファイルも区別はありません。
ドメイン名に続くパスに相当する部分は、そのまま、httpd がOSのファイルシステムからファイルを読みだすのに使われます。
まず、パソコンにドキュメントの構造通りフォルダやファイルを配置して、サーバなしでブラウズして確認しました。これを一括して、このレンタルサーバに転送しました。
転送はFileZillaで行いました。
サーバ上のサイトのindex.htmlを開いてリンクを開こうとすると、404(Page not found)
になります。
試行錯誤の結果、URLエンコード時に、"shift_jis" を指定して、リンクに設定すれば旨くいくことが分かりました。具体的には、
NuGet で「System.Text.Encoding.CodePages」をプロジェクトに加え、1度、以下の関数を呼び出すようにします。
|
URLのドメイン名以降のパスの部分について、スラッシュ記号で分割された、それぞれを以下のようにしてエンコードしました。
|
しかし、レンタルサーバはUnixだと思うので判然としません。すべてUTF-8で良いはずです。本当の問題は、FileZilla がサーバをsjisと自動認識することにありました。「UTF-8強制」と設定すれば最初のままで良かったと言うことです。
結局、HTML内に記述するhrefやsrc属性の値は、日本語のフォルダ名、ファイル名で良いと言うことです。ブラウザがUTF-8エンコードを施して get を送ります。
もちろん、UTF-8エンコードをした上で、hrefやsrc属性の値に設定してもOKです。ただし、スペースを含むと旨く行きません。もし、エンコードしたものをセットするならスペースの送り方は工夫がいるようです。
そもそも、UrlEncode関数のEncoding引数の働きは理解できません。Encodingで指定した文字列をURLエンコードするなら、入力の文字列はbyte[]でなければならないと思います。
入力の文字列が string型であると言うことは、UTF-16の状態で格納されていることを意味します。
「あ」を例に採ります。Unicode の 0x3042 です。 C# のstring型は、0x42、0x30と格納していると考えられますが、このエンディアンの問題は無視して考えます。
表_1.「あ」をURLencodeした結果
Encoding | 結果 |
utf-8 | %e3%81%82 |
shift_jis | %82%a0 |
UrlEncode関数の入力はstring型でUnicodeで表されています。UrlEncode関数は、入力された文字列をEncoding引数に合わせてエンコードします。エンコード結果のバイト列をバイトごとに順次 %xx の形式の文字列にします。
URLはサーバに送られ httpd によってデコードされることになるものと思います。
単に%の次の2文字が1バイトの値の16進数表記なので、URLエンコードのデコードはコード系に無関係に行えます。
Windowsであれば文字列の内部形式はsjisでもUTF-8でもないので、さらに内部形式に変換されることになります。
Linuxの場合、内部形式もUTF-8なのではないかと思います。したがって、URLのパスの部分をデコードした結果は、そのままファイルアクセスに使用されるのだと思います。
Chromeのアドレスバーに「http://mikeo410.minim.ne.jp/あ」と書いてみます。入力と、エンターを押して入力完了後の表示を示します。また、サーバに「あ」はないので404エラーとなりますが、サーバが返したエラーメッセージ中のパス表示を示します。
表_2.ブラウザのアドレスバーの入力
入力 | 入力後 | エラー表示 | 送られるリクエスト |
あ | あ | あ | GET /%E3%81%82 |
%E3%81%82 | あ | あ | GET /%E3%81%82 |
%82%a0 | %82%a0 | �� | GET /%82%a0 |
レンタルサーバにはファイルマネージャが付いており、ファイルの送受ができます。これは、HTTPプロトコルによるファイル転送を行っていると思います。
「あ.html」というファイルをパソコンで作成し、ファイルマネージャとFileZillaで転送してみます。FileZillaはサイトの文字コードを「自動検出」と設定しておきます。
表_3.ファイルマネージャとFileZillaで転送したファイルの見え方
転送手段 | ファイルマネージャ の表示 | FileZillaの表示 | 「UTF-8を強制」した FileZillaの表示 |
ファイルマネージャ | あ.html | あ.html | あ.html |
FileZilla | あ.html | ã.html | あ.html |
FileZilla はサーバが sjis と認識するらしく、0x82、0xa0、"html" と指定してファイルを転送したと考えられます。実際、サーバサイドスクリプトで取得される名前は、この通りでした。それにも係わらず、ファイルマネージャも、UTF-8を強制したFileZillaも正しく「あ.html」と表示しています。これは理屈に合いません。
また、自動検出のFileZillaは、UTF-8の「あ.html」を「ã.html」と表示します。これは、UTF-8のマルチバイト文字の先頭の 0xe3 が、sjis ではマルチバイト文字ではないので、ISO/IEC 8859など8単位コードの字形が引き当てられたものと考えられます。
1バイト/文字なのは0x7f以下に限られます。UTF-8とsjisはマルチバイト文字の先頭バイトが異なるので識別することは可能です。0x82、0xa0、"html" というファイル名は、UTF-8ではないので、親切にも変換してくれる仕組みがどこかにあるようです。
また、Linuxサーバは、FTPでフォルダやファイルを作る場合、UTF-8として不合理なコード列でも、そのまま作成されます。