FileReader()

FileReader クラスは、HTML5 世代の機能

File APIで出来ること
-ローカルにある画像をアップロードする前にプレビューを表示する
-ローカルにある画像をブラウザで加工してダウンロードする
-テキストファイルをブラウザで解析する
-データをJSONファイルとしてエクスポートして、インポートする
-大きなファイルを分割してサーバーに送信する

特に、「ローカルにある画像をアップロードする前にプレビューを表示する」ですね。

readAsDataURL メソッドは、指定された Blob ないし File オブジェクトを読み込むために使用
reader.readAsDataURL(file);
escape():16 進数エスケープシーケンスに置換
insertBefore:指定のノードを現在のノードの子ノードとして参照要素の前に挿入

inputで選択した複数画像をブラウザ上で表示させる

<style>
.thumb {
	height: 100px;
	width: 100px;
	border: 1px solid #000;
	margin: 10px 5px 0 0;
}
</style>

<input type="file" id="files" name="files&#91;&#93;" multiple /><br>
<output id="list"></output>
<script>
	function handleFileSelect(evt){
		var files = evt.target.files;

		for (var i = 0, f; f = files[i]; i++) {

			if (!f.type.match('image.*')) {
		        continue;
		      }

			var reader = new FileReader();

			reader.onload = (function(theFile){
				return function(e){
							var span = document.createElement('span');
		          span.innerHTML = ['<img class="thumb" src="', e.target.result,
		                            '" title="', escape(theFile.name), '"/>'].join('');
		          document.getElementById('list').insertBefore(span, null);
		        };
		      })(f);

			reader.readAsDataURL(f);
		}
	}

	document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>

初期

画像を選択

選択後
なんだこりゃーー!!すげー

では繋げてみましょう。

<?php
	  for ($i=0; $i<count($_FILES&#91;'files'&#93;&#91;'name'&#93;); $i++) {
    $file_ext = pathinfo($_FILES&#91;"files"&#93;&#91;"name"&#93;&#91;$i&#93;, PATHINFO_EXTENSION);
    if (/*FileExtensionGetAllowUpload($file_ext) && */ is_uploaded_file($_FILES&#91;"files"&#93;&#91;"tmp_name"&#93;&#91;$i&#93;)) {
      if(move_uploaded_file($_FILES&#91;"files"&#93;&#91;"tmp_name"&#93;&#91;$i&#93;, "upload/img/".$_FILES&#91;"files"&#93;&#91;"name"&#93;&#91;$i&#93;)) {
          echo $_FILES&#91;"files"&#93;&#91;"name"&#93;&#91;$i&#93; . "をアップロードしました。<br>";
      } else {
        echo "ファイルをアップロードできません。<br>";
      }
    } else {
      echo "ファイルが選択されていません。<br>";
    }
  }
  //アップロードできるファイルに拡張子の制限をかけたい時
  function FileExtensionGetAllowUpload($ext){
    $allow_ext = array("gif","jpg","jpeg","png","eps");
    foreach($allow_ext as $v){
      if ($v === $ext){
        return 1;
      }
    }
    return 0;
  }

?>
<style>
.thumb {
  height: 100px;
  width: 100px;
  border: 1px solid #000;
  margin: 10px 5px 0 0;
}
</style>
<form action="#" method="post" enctype="multipart/form-data">
<input type="file" id="files" name="files&#91;&#93;" multiple />
<input type="submit" value="Send">
</form>
<output id="list"></output>
<script>
  function handleFileSelect(evt){
    var files = evt.target.files;

    for (var i = 0, f; f = files[i]; i++) {

      if (!f.type.match('image.*')) {
            continue;
          }

      var reader = new FileReader();

      reader.onload = (function(theFile){
        return function(e){
              var span = document.createElement('span');
              span.innerHTML = ['<img class="thumb" src="', e.target.result,
                                '" title="', escape(theFile.name), '"/>'].join('');
              document.getElementById('list').insertBefore(span, null);
            };
          })(f);

      reader.readAsDataURL(f);
    }

    var output = [];
    for (var i = 0, f; f = files[i]; i++) {
      output.push('<li><strong>', escape(f.name), '</strong>(', f.type || 'n/a', ') -',
        f.size, ' bytes, last modified: ',
        f.lastModifiedDate.toLocaleDateString(), '</li>');
    }
    document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
  }

  document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>

ほお

php側にもちゃんと渡されています。

ファイルをdrag & drop

<style>
#drop_zone {
	height:100px;
	width:400px;
	background-color:#EEEEEE;
	display: flex;
	align-items: center;
	justify-content: center;
	color:white;

}
</style>
Drop files here
<div id="drop_zone">ここに添付ファイルをドロップ</div>
<output id="list"></output>

<script>
function handleFileSelect(evt){
	evt.stopPropagation();
	evt.preventDefault();

	var files = evt.dataTransfer.files;

	var output = [];
	for (var i = 0, f; f = files[i]; i++) {
		output.push('<li><strong>', escape(f.name), '</strong>(', f.type || 'n/a', ') -',
			f.size, ' bytes, last modified: ',
			f.lastModifiedDate.toLocaleDateString(), '</li>');
	}
	document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
}

	function handleDragOver(evt){
		evt.stopPropagation();
		evt.preventDefault();
		evt.dataTransfer.dropEffect = 'copy';
	}

	var dropZone = document.getElementById('drop_zone');
	dropZone.addEventListener('dragover', handleDragOver, false);
	dropZone.addEventListener('drop', handleFileSelect, false);
</script>

あ、これマジ凄い

preventDefault() は、その要素のイベントをキャンセルし、stopPropagation()は、親要素への伝播をキャンセル

dataTransfer:ドラッグを開始した時に、DataTransfer オブジェクトを取得する
addEventListener(‘dragover’,”,false)ドロップ領域に入っている間連続して発生
addEventListener(‘drop’,”,false)ドロップされた時に発生

jsで複数添付ファイルのtype, size, lastModifiedDateを表示する

var file = event.target.files[0]; で、ファイルオブジェクトを取り出す。

<input type="file" id="files" name="files&#91;&#93;" multiple />
<output id="list"></output>

<script>
	function handleFileSelect(evt){
		var files = evt.target.files;

		var output = [];
		for (var i = 0, f; f = files[i]; i++) {
			output.push('<li><strong>', escape(f.name), '</strong>(', f.type || 'n/a', ') -',
				f.size, ' bytes, last modified: ',
				f.lastModifiedDate.toLocaleDateString(), '</li>');
		}
		document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
	}

	document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>

jsで複数の初期化式

<script>
document.write("<p>");

for(var i = 1, j=10; i < 10; i++, j++){
	document.write("i = " + i + ", j = " + j + "<br>");
}

document.write("</p>");
</script>

toLocaleDateString()
->日付のみ抽出

<script>
var date = new Date();

document.write(date.toLocaleDateString());
</script>

addEventListener
イベント追加

<form>
<input type="button" id="ev" value="button" onclick="func1()">
</form>
<script>
function func1(){ alert("関数1が呼び出されました");}
var obj = document.getElementById("ev");

obj.addEventListener("click", func2, false);
function func2(){ alert("関数2が呼び出されました");}

obj.addEventListener("click", function(){
	alert("関数3が呼び出されました")
}, false);
</script>

つなげると、

<?php
	  for ($i=0; $i<count($_FILES&#91;'files'&#93;&#91;'name'&#93;); $i++) {
    $file_ext = pathinfo($_FILES&#91;"files"&#93;&#91;"name"&#93;&#91;$i&#93;, PATHINFO_EXTENSION);
    if (/*FileExtensionGetAllowUpload($file_ext) && */ is_uploaded_file($_FILES&#91;"files"&#93;&#91;"tmp_name"&#93;&#91;$i&#93;)) {
      if(move_uploaded_file($_FILES&#91;"files"&#93;&#91;"tmp_name"&#93;&#91;$i&#93;, "upload/img/".$_FILES&#91;"files"&#93;&#91;"name"&#93;&#91;$i&#93;)) {
          echo $_FILES&#91;"files"&#93;&#91;"name"&#93;&#91;$i&#93; . "をアップロードしました。<br>";
      } else {
        echo "ファイルをアップロードできません。<br>";
      }
    } else {
      echo "ファイルが選択されていません。<br>";
    }
  }
  //アップロードできるファイルに拡張子の制限をかけたい時
  function FileExtensionGetAllowUpload($ext){
    $allow_ext = array("gif","jpg","jpeg","png","eps");
    foreach($allow_ext as $v){
      if ($v === $ext){
        return 1;
      }
    }
    return 0;
  }

?>
<form action="#" method="post" enctype="multipart/form-data">
<input type="file" id="files" name="files&#91;&#93;" multiple />
<input type="submit" value="Send">
</form>
<output id="list"></output>

<script>
  function handleFileSelect(evt){
    var files = evt.target.files;

    var output = [];
    for (var i = 0, f; f = files[i]; i++) {
      output.push('<li><strong>', escape(f.name), '</strong>(', f.type || 'n/a', ') -',
        f.size, ' bytes, last modified: ',
        f.lastModifiedDate.toLocaleDateString(), '</li>');
    }
    document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
  }

  document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>

いいですね!

onChange()メソッド

onChangeとは、フォーム内のエレメント(要素)の内容が変更された時に起こるイベント処理

sample

<form name="link">
<select name="linkselect" onChange="confirm()">
<option value="">選択してください</option>
<option value="https://products.office.com/ja-jp/exchange/exchange-online">Microsoft Exchange Online</option>
<option value="https://willcloud.jp/">Will Mail</option>
<option value="http://www.cybersaas.jp/">CYBERMAIL Σ</option>
</select>
</form>
<script>
function confirm(){
	obj = document.link.linkselect;

	index = obj.selectedIndex;
	if(index != 0){
		href = obj.options[index].value;
		location.href = href;
	}
}
</script>

multiple属性による複数ファイルアップロードが上手くいかない?

up.phpファイル
postでphp側に渡して、var_dumpします。

<?php
print_r('<pre>');
var_dump($_FILES);
print_r('</pre>');
?>

<html>
<head>
    <title>multiple upload</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<form action="#" method="post" enctype="multipart/form-data">
Files:<input type="file" name="upfile&#91;&#93;" multiple>
<input type="submit" value="submit">
</form>
</body>
</html>

初期状態 ※ファイルは選択していません。

01.gifを選択

選択されてます。

続いて02.gifを選択

02.gifも選択されています。

post(submit)します。

何故だ? 02.gifしかアップロードされていない!?

multipleが効いていないのでは?と、multipleを、multiple=”multiple”に変えたり、phpファイルとhtmlファイルに分けたり、サーバー環境を変えたり、html5shivをヘッダーに入れたりしたが全くダメで、ずっと悩み続け、
ふと、画像選択時にctlコマンド押下で二つ選んだら、

おいおいおい、まじかよ?

今日は実質朝からこれしかやってないんだけど。。。

ファイルをアップロード

ファイルのmax sizeを指定します。

<form method="post" action="#" enctype="multipart/form-data">
		ファイル:<input type="file" name="up_file"><br>
		<input type="submit" value="upload">
		<input type="hidden" name="MAX_FILE_SIZE" value="4194304" />
</form>

fileが一時保存の領域に保存されているか確認

<?php
	if(is_uploaded_file($_FILES&#91;'up_file'&#93;&#91;'tmp_name'&#93;)){
		if(move_uploaded_file($_FILES&#91;'up_file'&#93;&#91;'tmp_name'&#93;,"./".$_FILES&#91;'up_file'&#93;&#91;'name'&#93;)){
			echo "uploaded";
		} else {
			echo "error while saving.";
		}
	} else {
		echo "file not uploaded.";
	}

?>
<form method="post" action="#" enctype="multipart/form-data">
		ファイル:<input type="file" name="up_file"><br>
		<input type="submit" value="upload">
		<input type="hidden" name="MAX_FILE_SIZE" value="4194304" />
</form>

保存場所を/upload/img/test.gif と指定します。

if(is_uploaded_file($_FILES['up_file']['tmp_name'])){
		if(move_uploaded_file($_FILES['up_file']['tmp_name'],"./upload/img/test.gif")){
			echo "uploaded";
		} else {
			echo "error while saving.";
		}
	} else {
		echo "file not uploaded.";
	}

保存されています。

phpでメールボックスをつくろう3 DBと接続

メール送信後のテーブルを作成します。file送信の機能は後から追加の予定。

create table mail.sends(
	id int unsigned auto_increment primary key,
	username varchar(41),
	destination varchar(41),
	subject varchar(255),
	body varchar(255),
	file1 varchar(255),
	file2 varchar(255),
	sendtime datetime default null
);

DBへの接続 ”to”がpostされたら、DBに入れます。

session_start();
if(isset($_POST["to"])){
	$username = $_SESSION["username"];
	$destination = htmlspecialchars($_POST["to"]);
	$subject = htmlspecialchars($_POST["subject"]);
	$body = htmlspecialchars($_POST["body"]);
	$date =	date("Y-m-d h:i");

	$dsn = "mysql:dbname=mail;host=localhost";
	$user = "hoge";
	$password = "hogehoge";
	 
	try {
	    $dbh = new PDO($dsn, $user, $password);
	} catch (PDOException $e){
	    print('connection failed:'.$e->getMessage());
	}

	$stmt = $dbh -> prepare("INSERT INTO sends (username, destination, subject, body, sendtime) VALUES(:username, :destination, :subject, :body, :sendtime)");
    $stmt->bindParam(':username', $username, PDO::PARAM_STR);
    $stmt->bindParam(':destination', $destination, PDO::PARAM_STR);
    $stmt->bindParam(':subject', $subject, PDO::PARAM_STR);
    $stmt->bindParam(':body', $body, PDO::PARAM_STR);
    $stmt->bindParam(':sendtime', $date, PDO::PARAM_STR);
    $stmt->execute();
}

メールを新規作成します。

ブラウザ上の挙動

mysql側
select * from sends

mysql> select * from sends;
+----+----------+-------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------+-------+-------+---------------------+
| id | username | destination | subject                                                  | body                                                                                       | file1 | file2 | sendtime            |
+----+----------+-------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------+-------+-------+---------------------+
|  1 | sample   | tanaka      | 2,000円分の割引クーポンが発行されました                  | 対象ショップ
-31 Sons de mode
-CANAL JEAN
-ORiental TRaffic
-GRACE CONTINENTAL
       | NULL  | NULL  | 2018-03-26 10:23:00 |
+----+----------+-------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------+-------+-------+---------------------+
1 row in set (0.00 sec)

入ってますね。
時間は $date = date(“Y-m-d h:i”); ではなく、$date = date(“Y-m-d H:i”); ですね。

次は、
1.添付ファイルを送りたい。
2.メールの宛先がusernamesの中になければ、宛先なしで送信エラーとしたい。
3.send itemをクリックすると、sendテーブルから送信メールを呼び出したい。

あれ、まてよ、
受け取るtestは、receiveテーブルから読み込む想定なので、receiveテーブルにもinsertしないといけない?

phpでメールボックスをつくろう2 新規作成

<div class="flex-2">
   <?php if($_GET&#91;"compose"&#93; == 'new'): ?>
		<form action="" method="post">
			宛先:<br>
			<span id="fs-s">※送り先のユーザ名を入力してください</span>
			<input type="text" name="to" size="90%"><br>
			件名:<br>
			<input type="text" name="subject" size="90%"><br>
			本文:<br>
			<textarea name="body" rows="12" cols="100%"></textarea>
			</p>
			<p>
			<input type="submit" value="送信">
			</form>
   <?php endif; ?>
</div>

宛先と本文を必須(required)にする

<?php if($_GET&#91;"compose"&#93; == 'new'): ?>
		<form action="" method="post">
			宛先
			<span id="fs-s">※必須</span><br>
			<input type="text" name="to" size="90%" required><br>
			件名<br>
			<input type="text" name="subject" size="90%"><br>
			本文
			<span id="fs-s">※必須</span><br>
			<textarea name="body" rows="12" cols="100%" required></textarea>
			</p>
			<p>
			<input type="submit" value="送信">
			</form>
   <?php endif; ?>

DBに入れるため、postの内容を受け取り、変数に格納する

session_start();
if(isset($_POST["to"])){
	$to = $_POST["to"];
	$subject = $_POST["subject"];
	$body = $_POST["body"];
}

送信後はパラメータを”?compose=done”に変更する

<?php if($_GET&#91;"compose"&#93; == 'new'): ?>
		<form action="?compose=done" method="post">
			宛先
			<span id="fs-s">※必須</span><br>
			<input type="text" name="to" size="90%" required><br>
			件名<br>
			<input type="text" name="subject" size="90%"><br>
			本文
			<span id="fs-s">※必須</span><br>
			<textarea name="body" rows="12" cols="100%" required></textarea>
			</p>
			<p>
			<input type="submit" value="送信">
			</form>
   <?php elseif($_GET&#91;"compose"&#93; == 'done'): ?>
   			<p>メール送信が完了しました</p>
   <?php endif; ?>

おお、なんか凄い疲れた。

phpでメールボックスをつくろう1

まず初期状態

<?php
session_start();
?>
<style>
h1 {
	display:inline;
}
#out {
/*	display: inline;*/
	float:right;
}
.flex-container {
  display: flex;
}
.flex-1{
  flex:2;
  height:400px;
  background-color:#f5f5f5;
}
.flex-2{
  flex:7;
}
</style>
<?php if(isset($_SESSION&#91;"username"&#93;)): ?>
<h1><?php echo $_SESSION&#91;"username"&#93;; ?>さんのメールボックス</h1>
<div id="out"><a href="logout.php">ログアウト</a></div>
<hr>
<div class="flex-container">
<div class="flex-1">
</div>
<div class="flex-2">
</div>
</div>
<?php else: header('Location: login.php'); ?>
<?php endif; ?>

sampleというユーザ名でログインした状態です。

メニューを作ります。
gmailやhotmailではメール新規作成などはgetパラメーターを使っているので、ここでは”?compose=new”とします。

<div class="flex-1">
<a href="?compose=new" class="square_btn">新規作成</a>
<ul>
		<li><a href="">Inbox</a></li>
		<li><a href="">Junk Email</a></li>
		<li><a href="">Sent Items</a></li>
		<li><a href="">Deleted Email</a></li>
</ul>
</div>

getパラメータでcomoseがnewの場合、フォームを表示させたいので、

<div class="flex-2">
   <?php if($_GET&#91;"compose"&#93; == 'new'): ?>
		<p>メール新規作成</p>
   <?php endif; ?>
</div>

うまく動いているようです。