[IE対策も] UTF-8フォームから別の文字コードへPOSTする際の文字化け解消法


こんにちは、ふじーにょ(@fujinyo)です。
異なる文字コードでのフォームPOST時の文字化けを解消することができたので備忘録として記事にしておきます。

今回は、UTF-8フォームからShift-JISへのPOSTを想定しています。

[IE対策も] UTF-8フォームから別の文字コードへPOSTする際の文字化け解消法

まずはダメなパターン

基本の送信側HTMLフォームと、受け手側PHPのソースが以下です。

utf8.html
ファイルの文字コード: UTF-8

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>UTF-8フォーム</title>
	</head>
	<body>
		<h1>UTF-8フォームからSJISへ送信</h1>
		<form method='post' action='./sjis.php'>
			<input type='text' name='string'>
			<input type='submit' value='UTF-8で送信'>
		</form>
	</body>
</html>

sjis.php
ファイルの文字コード : Shift_JIS

<?php
// POSTデータを受けて、特殊文字を HTML エンティティに変換
$string = (string)filter_input(INPUT_POST, 'string');

if ($string) {
	$string = htmlspecialchars($string, ENT_QUOTES, 'SJIS-win');
} else {
	$string = 'no data.';
}
?>
<html>
	<head>
		<meta charset="Shift_JIS">
		<title>SJISページ</title>
	</head>
	<body>
		<h1>UTF8フォームから届いた文字列</h1>
		<?php echo($string); ?>
	</body>
</html>

試して頂けるとわかりますが、POSTしてもなにも表示されません
sjis.phpの6行目で htmlspecialchars を使っていますが UTF-8 でPOSTされたデータを SJIS で変換しているため、空の文字列が返されるようです。

formタグにaccept-charsetを指定する

解決方法として、formタグにaccept-charset属性を追記してあげます。
編集したformタグの部分1行が以下です。

utf8.html


<form method='post' action='./sjis.php' accept-charset='Shift_JIS'>

これで、POSTしてみると見事に送信した文字列が正常に表示されました。
し、しかし、、、Chrome、FireFox、Operaでは正常に動作するもののIEだけうまくいきませんでした。

どうも、IEは accept-charset を無視するようです。

POSTする際にdocument.charsetを指定する

IEの解決方法として、フォームのPOST時(正確にはsubmitボタンが押されたら)にdocument.charsetを指定して文字コードを変えてやります。
編集した部分のソースが以下です。

utf8.html


<input type='submit' value='UTF-8で送信' onclick="document.charset='Shift_JIS';">

これでどうでしょう。IEでもちゃんと文字化け無しで表示されました。おめでとうございます。
試しに、他の文字列でも正常かどうかを確認してみましょう。ブラウザの「戻る」でフォーム画面へ戻ってみます。

あ、、、あれ?フォーム側が文字化けしてる。。。
変換してPOSTしたので、戻ってもそのままになっているのか。まだ終わらない…

JavaScriptで解決

戻ってきた際に、文字コードがUTF-8であるかチェックしてUTF-8でなければ変換する処理をJavaScriptで追加します。

utf8.html

<script type='text/javascript'>
	var isMSIE = /*@cc_on!@*/false;
	if (isMSIE) {
		if(document.charset !== "utf-8"){
			document.charset = "utf-8";
			location.reload();
		}
	}
</script>

こんな感じです。
これで、IEでフォームへ戻っても正しく表示されました。めでたし、めでたし。

では、最終のコードを。

utf8.html
ファイルの文字コード: UTF-8

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>UTF-8フォーム</title>
		<script type='text/javascript'>
			var isMSIE = /*@cc_on!@*/false;
			if (isMSIE) {
				if(document.charset !== "utf-8"){
					document.charset = "utf-8";
					location.reload();
				}
			}
		</script>
	</head>
	<body>
		<h1>UTF-8フォームからSJISへ送信</h1>
		<form method='post' action='./sjis.php' accept-charset='Shift_JIS'>
			<input type='text' name='string'>
			<input type='submit' value='UTF-8で送信' onclick="document.charset='Shift_JIS';">
		</form>
	</body>
</html>

sjis.php
ファイルの文字コード : Shift_JIS

<?php
// POSTデータを受けて、特殊文字を HTML エンティティに変換
$string = (string)filter_input(INPUT_POST, 'string');

if ($string) {
	$string = htmlspecialchars($string, ENT_QUOTES, 'SJIS-win');
} else {
	$string = 'no data.';
}
?>
<html>
	<head>
		<meta charset="Shift_JIS">
		<title>SJISページ</title>
	</head>
	<body>
		<h1>UTF8フォームから届いた文字列</h1>
		<?php echo($string); ?>
	</body>
</html>

編集したのは、HTMLファイル側だけでしたね。
では、また。

[参考] ページの文字コードとは違う任意の文字コードをformから送信する方法
[参考] BK通信 – ブラウザのバッドノウハウ <form> 編
[参考] htmlspecialchars

[PR] 「結さん」があなたに代わって開発案件の依頼主を探します

  • 「既存のクライアントにギャラアップは言いにくい」
  • 「営業活動する時間がないし、苦手」
  • 「仕事が途切れたらどうしよう」

ITエンジニアのこんな悩みを「結さん」が解決してくれます
結さんへの無料会員登録後は提案メールを待つだけです!

関連記事