■default ---■fontsize --70% --80% --100% --120% --140% --- --■scroll_switch

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

shift-JISだと0x5cのところで$_FILESの名前が切れてしまう

文字コードってのがいまだになんだかよく分かってないんですが、それでも何とかホームページとかスクリプトとかは書けます。
ちなみにここはUTF-8という文字コードで書かれています。
書かれていますというか、出力されています。
未確認飛行物体みたいな名前ですね。
Unicode (or UCS) Transformation Format, 8-bit encoding form
の略らしいです。
ユニコードが何のことかよく分かりません。
ユニクロがまた新しい事業展開でもしたのかと思いました。

その他にブログなどで使われている文字コードで代表的なのは
・EUC-JP(Extended Unix Code)
・shift-JIS

EUCは英会話教室みたいですね。
私はshift-JISをよく使っています。ローカルのパソコンのテキストエディターもshift-JISの設定になっています。
この文字コードの解釈をパソコンが間違ってしまうと、文字化けしたり、図形みたいになったり、有りもしない噂を立てられたりしてしまいます。
なので、ホームページとかのHTMLの冒頭には
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
とか定義が書かれています。charset=utf-8"の所です。
ヘッダー情報という所に書かれているので、パッと見では見えませんけど。
右クリックして「ソースの表示」とかすると見れます。
これによって皆さんのお使いのブラウザは判断して表示しているのです。
同じページに違う文字コードがあると文字化けします。
このブログにギルブレスの定理検索とか、誕生日マジック作成プログラムなど有りますが、あの部分はジャバスクリプトという方式で書かれていまして、また別の入り口から出力されています。
私、先ほどローカルのパソコンはshift-JISといいましたが、ジャバスクリプトもshift-JISで書いています。
ブログはUTF-8なのでそのままだと文字化けします。
なので、ジャバスクリプトを呼び出す時にこういう風に書いています。
<script type="text/javascript" charset="Shift_JIS" src="http://blog-imgs-44.fc2.com/s/e/c/section009/birthday_count.js" ></script>
charset="Shift_JIS" のところがみそで、この外部プログラムに関してはその文字コードで解釈してください、ということです。

他にも、元からUTF-8で統一して書くとか、いろいろ方法は有りますが、いずれにしても一工夫必要なのです。
とくに、WEBブログラムは
・サーバー
・サーバーのHTMLデーモン
・ユーザーのブラウザ
・ジャバスクリプト(ブラウザ上で動くプログラム)
・HTML(文章本体)
・CGI(PHPなどのサーバー上のプログラム)
・CSSなどの外部プログラム
・SQL(データベース)
と、からみあってますので、気が遠くなります。

ところで、文字コードってモテコーデ(もてるこーでぃねーと)に響きがにていますね!!

おもろいのが飛び出ましたところで本題に行きます。
ここからくそ長いので、フラリッシャーは読まなくていいです。
---------------------------------------------------------------
---------------------------------------------------------------
事情は様々にしろ、PHPをshift-JISで書いている人がいると思います。
私はもっぱら
・PHP shift-JIS
・HTML shift-JIS
・javascript shift-JIS
・MYSQL UFT-8(だったような)
です。
理由はめんどくさいからです。
別に仕事でやっているわけではないので、マナーは気にしません。
しかも、受け渡しの時に変換してやれば済む話なので、特に問題になりません。


で、何で今までこの問題に直面しなかったのか不思議なのですが、
$_FILES、で受け渡されたファイルの名前に0x5cのコードが入っているとちゃんと名前が取れない。
addslashes とかマルチバイト関数とか使う前にPHPが勝手に判断してファイルネームを$_FILESにいれます。
HTMLフォームのtype="file"ではフルパスが来ません。
とどのつまり、0x5cが\と解釈されて、フォルダ名だと思われて切られてしまいます。
ソーラン節開催申請表_フォーマット.xls
とかのファイル名だった場合、表のところで切られて
_フォーマット.xls
になっちまいます。
ソ,噂,浬,欺,圭,構,蚕,十,申,曾,箪,貼,能,表,暴,予,禄,兔,喀,媾,彌,拿,杤,歃,濬,畚,秉,綵,臀,藹,觸,軆,鐔,饅,鷭,偆,砡,纊,犾
がファイル名に入っていたらアウツ。
$_FILESは$POSTとか$GETに入らないので(みたいなので)、工夫の仕様が有りません。
PHPの設定とかApacheの設定とかいろいろ変えてみたけど、・・・が、ダメ。
以前までは、アップロード処理のプログラムはUTF-8にしてたみたいですが、記憶にございません。
もうコリャ、全コードUTF-8に書き直しか。
めんっどっくせー。
事情はどうあれ、そんな時はこれ。
私はこれで解決しました。

別のテキストフォームでフルパスを別個で渡す。


まず、HTMLのソース
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
//ヘッダーのところで
<SCRIPT language=JavaScript src="upload.js"></SCRIPT>

//本文の適当なところで
<form method="POST" action="upload.php" name="uplodef" id="uplodef" enctype="multipart/form-data" onsubmit="sjis_uplode_filename_ar('uplode','_nm',3);">
<input type="hidden" name="mode" value="upload">
<input type="hidden" name="MAX_FILE_SIZE" value="10000000">

<input name="uplode0" id="uplode0" value="" size="80" type="file" ><br>
<input name="uplode1" id="uplode1" value="" size="80" type="file" ><br>
<input name="uplode2" id="uplode2" value="" size="80" type="file" ><br>

<input name="f_n_ary[uplode0]" id="uplode_nm0" value="" type="hidden" >
<input name="f_n_ary[uplode1]" id="uplode_nm1" value="" type="hidden" >
<input name="f_n_ary[uplode2]" id="uplode_nm2" value="" type="hidden" >

<input type="submit" class="btn" value="保存" >
</form>
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
まず、
onsubmit="sjis_uplode_filename_ar('uplode','_nm',3);"
フォームを送る直前にこのプログラムを動かします。
このジャバスクリプトのソースは後で出てきます。
<input name="uplode0" id="uplode0" value="" size="80" type="file" ><br>
が0~2まで3つ有りますが、これはいくつでもOKです。
それと同じ数の
<input name="f_n_ary[uplode0]" id="uplode_nm0" value="" type="hidden" >
を用意します。
ファイルフォームのid="uplode0"で設定した名前を
非表示フォームのname="f_n_ary[uplode0]" の[]括弧の中身と合わせます。
この場合はuplode0です。
uplode0、自体の名前は何でもOKですが、複数アップロードする場合は後ろを数字にして連番にして下さい。

sjis_uplode_filename_ar('uplode','_nm',3);
の一番初めの引数は「uplode0」の連番を取った名前
2番目の引数は非表示フォームのIDの為の尻尾
3番目の引数は送るフォームをいくつにするかです。指定しないと1っこだけです。

それで
非表示フォームの id="uplode_nm0" はuplode0の連番を取った名前+2番目の引数の尻尾+連番
にします。


次はjavascript
upload.js
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
//-------------------------------------//-------------------------------------
//-------------------------------------//-------------------------------------
function sjis_uplode_filename_ar(bes_nm,til,kosuu){//ベースのIDナンバー 名前用の尻尾ID (nameは='元のIDナンバー'にする) 複数ある場合連番で繰り返し
if(!til){til="_nm_";}
if(!kosuu){//一個だけの場合
document.getElementById(bes_nm + til).value = document.getElementById(bes_nm).value;
}
else{
for (i = 0; i < kosuu; i++) {//kosuu が設定されている場合は複数なので連番をつけて繰り返し処理
document.getElementById(bes_nm + til + i ).value = document.getElementById(bes_nm + i ).value;
}
}

}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
これで送る直前に
f_n_ary[uplode0]の値に対応したname="uplode0" のフルパスの名前が入りますのでPHPに引き渡せます。
javascriptの状態でファイル名だけ切ってもいいのですが、せっかくなので、何かに使えるかもしれないし、そのまま渡します。
あとでPHPのマルチバイト関数で判断します。

次はPHP
upload.php
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
<?php
//前処理でフォームの値を同じ変数に入れてください。
//今回は非表示フォームのname="f_n_ary[uplode0]" のf_n_aryを配列で受け取っています。
//$_FILESはスーパーグローバルなので気にしない。ちなみにfileが1っこでも配列できます。
$hozon_basyo = "./data-box";//PHP側の保存場所
up_lord_file($hozon_basyo,$f_n_ary);//関数呼び出し
exit;
////////////////////////////////////////////////////////////////
//function up_lord_file(保存先、ローカルのフルパス配列)戻り値はfalseかアップロードしたfile数
function up_lord_file($hozon_basyo = '' ,$f_n_ary = false){//ファイルアップロード
$co = 0;
if(!isset($_FILES) || !is_array($_FILES)){ return false ;}//$_FILESが無かったら処理中断
foreach ($_FILES as $key => $fy) {
//if ($fy['error'] == UPLOAD_ERR_OK) { //エラーを見てもよい
if($fy['size'] > 0 ){//サイズが確認されたら処理する
$moto = str_replace ('\\','/',$fy['tmp_name']);//添付データの場所をWindowsの場合\をバックスラッシュにしてfileパスにする
if(is_array($f_n_ary)){//shiftJIS用の名前配列が着ていたらそちらを使用する,"JIS"
$rt = $f_n_ary[$key];//一旦変数に入れる
$rt = stripslashes($rt);//PHPでマジッククオートになっている場合スラッシュをとる
$rt = mb_substr($rt, mb_strrpos($rt,"\\","Shift_JIS")+1);//\マークより後ろの文字列をよみとる(これがファイル名)このmb_strrposを通すためにこれだけ苦労しています。
}
else{
$rt =$fy['name'];//upload.jsを使わなかった場合。そのまま
}
$saki = $hozon_basyo.'/'.$rt;//コピーファイル先(保存パスとファイル名をくっつける)
if(rename ( $moto , $saki )){//テンプデータを所定の場所に移動。move_uploaded_file() の方がいいらしいけど動かないので取り合えずrename。もしくはcopy
//uploadした後に何か処理したい場合はここに書く
//ちなみにMYSQLなどに登録する場合などはまたエスケープを付け直す $rt_es = addslashes($rt);
$co ++;//処理したらカウントアップ
}
}
}//foreach ($_FILES as $key => $fy)終わり
return $co ;//処理したfile数を返す
}//function up_lord_file終わり
?>
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////

と、まあ、PHPを書いている人には常識かもしれません。
が、私自身が忘れると思いますのでめもっておきます。


script_ms9
スポンサーサイト
ブログ内検索ワード
マジック / フラリッシュ / デザイン / ~のコツ / プログラム関連 /
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。