FormDataを使ったajaxのpostデータ送信は文字化けするから気をつけろ

2019/10/01

Javascript テクノロジー プログラミング

t f B! P L
WEBページからデータ送信をする場合に、HTMLタグのformを使う方法と、javascriptのみでFormData関数を使ってkey=valueデータ構築をして送信する方法があります。 その他にもjavascriptでformタグやらinputタグを仮想DOMに作ってsubmitするという方法もあるが、HTML方式と同じなので今回は上記2パターンで考えてみる事にする。 HTMLタグ方式は、formタグに、encodingなどを属性記述して、送信すればいいのだが、javascriptのFormDataで送信すると、どうやらContent-Typeが "Content-Type: multipart/form-data; boundary=" と自動的になってしまうため、受け取りサーバーのPHPがほぼデフォルト状態であれば、基本的に文字化けする。 これにハマって半日費やしてしまったため、ブログに痕跡を残しておくことにした。

ajaxのnew XMLHttpRequest()でsetRequestHeaderをセットしたのでは駄目なのか?

XMLHttpRequest()インスタンスで定義した変数にsetRequestHeaderでヘッダ情報をセットする方法だが、他のサイトではこの方法を推奨しているが、FormDataで送信する際に、"Content-Type"には、boundaryというhash情報を付けなくてはいけないため、これを簡易にjsで扱うことは非常に困難なため、この方法は厳しいという判断をした。

HTMLタグをFormDataの送り値にセットしたら?

基本的にHTMLタグを記述するぐらいなら、そのままform.submitした方が早いので、この方法は考えなかったのだが、仮想formを作って属性セットしたらどうなるか試してみたところ、あえなく撃沈。 どうやらFormDataインスタンスによる扱いという点で、Content-Typeは同じ結果になるようです。

最終的な解決方法

どうやら、ブラウザのrequest-headerを見てみると、文字列じたいの送っているデータには問題がなく、やはり"Content-Type"が正常にUTF-8として送信してくれないという、HTMLのバグとも言える仕様に問題があるため、受け取り側のPHPで対処するのが手っ取り早い。 出来る手段はいくつかあるが、以下の2つが最も確実で手っ取り早いと考えられる。
1. mb_string_encoding()でエンコード文字列を変換して対応 2. php.iniのmbstringのinputを"auto"から"UTF-8"に強制変更する。
サーバーの設定が変えられるのであれば、2番をセットすれば、問題なく完了しますl. しかし、サーバー設定を変えられない場合は1番しか残されていないのですが、この場合、送られてくるHTMLエンコードがASCIIやらHTML-ENTITIESやらとやたらと面倒くさい。 そこで1番の対応として、javascriptでマルチバイト文字列をencodeURICompornent(...)変換して送信し、受け取ったPHPでurldecodde(...)すれば、文字列を正常に送付することができる。 汎用性を設けるのがめんどくさい場合は、マルチバイトに関係なく、全てにurlencodeをセットするという荒業も悪くないかもしれない。 なんにせよ、マルチバイトって今でもめんどくさい存在なのは間違いないことが改めて理解できた!!

前回記事

[Javascript] もっと便利にサーバーにファイルをアップロードする方法

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ