menu

Web制作のTipsとかアレコレ。

動画ファイルアップロード前に、ローカルで適合チェック(PHP+Javascript)

2013.09.14

動画のアップロードをするためのスクリプトをPHPで書いてたんですけど、完成してからどうにも気に入らず、あまり得意ではないJavascriptを使って手直ししたらカナリ良くなったという話。

そもそもHTMLのフォームでPOSTしたファイルに対して重要なのがエラーチェック。

ファイルサイズ、ファイル名(2バイト文字が入ってたらサーバーが嫌がるもんで)、ファイル形式、ファイル名の重複など、$_POSTデータと$_FILESデータから一通りチェックする過程を書いてて、ふと気付いた。

これ、エラーチェックウンヌンする前に、POSTで受け取った瞬間にテンポラリーフォルダに全力でアップロードを始めてやがる。(それすら知らなかったorz)

出来ればサーバーにも回線にも余計な負荷をかけたくねぇなぁ・・・ローカル側でチェックしないとね・・・と思ったので、おもむろにGoogle先生に尋ねてみました。

「フォーム入力時にファイルが適合してるかどうかチェックしてくれるJavascriptを教えて!!」

すると、まあいろいろ出してくれたんですけど、なんかjQuery持ち出したり必要以上に大げさそうなのが多く、見るのが面倒になってきたので適当に自分で書いてみたら見事に機能してびっくりというわけです。

要は、POSTしたデータを受け取る側でチェックするまでに、最低限の条件に適合しないファイルはPOST出来ないようにしちゃうのが一番いいってことですわな。

動画をアップロードしているディレクトリのファイル名一覧をPHPで拾ってきて、ファイル名重複チェックとデータサイズチェックはJavascriptでやるという方針で。

まず、サーバー側からファイル名一覧をいただく。


$movieDirectory = "uploads/";
if ($uploadDirectory = opendir($movieDirectory)) {
    while (false !== ($fileName = readdir($uploadDirectory))) {
    if(!(preg_match("/^\.{1,2}$/", $fileName))){
         $fileInDir[] = strtolower($fileName);
        }
    }
 closedir($uploadDirectory);
}
$fileArray = '"'.implode('","', $fileInDir).'"';

最後のimplodeで先頭と末尾にクォーテーションを加えてやることで、Javascriptに配列として渡す準備が整いにけり。

とりあえず、ファイルサイズとファイル名だけチェックするJavascriptです。

function check(){
	//ディレクトリ内のファイル名の配列をPHPから受け取る
	var fileArr = [<?=$fileArray?>];
	//inputフィールドに入力されたファイルを取得
	var fileName = document.getElementById("movieFile").files;
	//出力メッセージを用意
	var list = "";
	//エラー判定用のダミー変数
	var judge = 0;
	//なんやファイル一つでも配列で取って来るらしいのでforで回すことになってもーてる
	for(var i=0; i<fileName.length; i++){
		var movieFileSize = Math.ceil(fileName[i].size/1048576);
		if(fileName[i].size > 31400000){
				list += "<span style=\"color:#f00\">ファイルサイズが大きすぎます!(" + movieFileSize + "メガバイトもあるぞ!)</span><br>";
		} else {
				list += 'ファイルサイズは大丈夫です。<br>';
				judge ++ ;
		}
		// ディレクトリ内のファイル名と一致してるかしらべて、一致してたらエラーメッセージ出す
		var lowcaseFileName = fileName[i].name.toLowerCase();
		fileResult = fileArr.indexOf(lowcaseFileName);
			if(fileResult == -1){
				list += 'ファイル名は大丈夫です。<br>';
				judge ++ ;
			}else{
				list += '<span style=\"color:#f00\">ファイル名がかぶってますよ!</span><br>';
			}
		list += "ファイル名:" + fileName[i].name + "<br>" + "ファイルサイズ:約" + movieFileSize + "Mバイト<br>" ;
	}

			document.getElementById("result").innerHTML = list;
			document.getElementById("result").style.display = "block";
		//サイズも名前もOKだったらアップロードボタンを表示させる
		if(judge == 2){
			 document.getElementById('newFileSubmit').disabled = null;
		}else{
			 document.getElementById('newFileSubmit').disabled = "disabled";
		}
	}

ほんで、フォーム。

<form method="post" action="movieUpload.php" enctype="multipart/form-data">
	<p>ファイル: <input type="file" name="movie" id="movieFile" onchange="check()">
	<p><input type="submit" id="newFileSubmit" value="アップロード" disabled>
</form>
<!-- 結果表示用領域 -->
<div id="result" style="padding: 20px; border: 1px dotted #f00; width: 420px; display: none;"></div>

ポイントはJavascriptの条件判定で、ファイルサイズ・ファイル名それぞれの項目でOKだったらjudgeという変数に1を足していって、それが2にならなかったらアップロードボタンを有効化してくれない点。やり方はダサいんですけど、考えるの面倒だったからこれで済ませてます(笑)

今後、ファイル名の2バイト文字チェックやら拡張子チェックやら、チェック項目が増えたらここの数字を変えてやるってことで。賢いやり方教えてください。すぐ書き換えますので。

で、最初はJsの方の85-87行目のelse節は付けてなかったんですが、一度適合ファイルを選択してアップロードが有効になったあとにすぐ不適合なファイルを選択した場合、アップロードボタンが有効になったまんまになっちゃうので必要でした。

あと、ファイル選択のinputフィールドからファイル情報を取得するのって、配列で取って来るのでしょうか?一つだけの入力ボックスなのに、配列で処理しないとエラーがでちゃうんですけど。詳しい人、教えてくださいませ。

というわけで、いかにもJs書きなれてない人のスクリプトでお目汚しかもしれませんが、自分用の備忘録と、万が一、億が一誰かの役に立てば幸いと、そんなエントリーでした。

おしまい。

Comments

please leave your comment...

▲ Page Top