2016 06 29 の学び - CSVファイルのGUIインポート-エクスポートツールを実装した
方向を見失いそうになってたので、まずは目標を簡略化しました。
(1) 目標の簡略化
"ユーザーは「ファイルを選択する」ボタンを押すとファイル選択ウィンドウが出てきてファイルを選べる。CSVファイルを選択して、「アップロード」ボタンを押すと裏でsample.shが動き出し、様式の整った新しいCSVファイルが自動的にユーザーのPCへダウンロードされる。"
→ (簡略化1) ユーザーがブラウザ上で選択したファイルを、会社サーバーの指定したディレクトリへ保存できる仕組みを実装しよう。
→ (簡略化2) シェルスクリプトをブラウザ上で実行しよう。
→ (簡略化3) 会社サーバー内にあるファイルを、ユーザーがブラウザ上からダウンロードできる仕組みを実装しよう。
→ (簡略化4) 上記3つをまとめてみよう。
全部一気に考えるのではなくて、全部小分けしてみることにしました。
(2) 簡略化1について
(2-1) 参考サイト
(2-2) やったこと
(2-2-1) htmlでフォーム定義
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>sample</title>
</head>
<body>
<form action="upload.php" method="post" enctype="multipart/form-data">
csvファイルをアップロードして下さい<br><br>
<input type="file" name="upfile" size="30"><br>
<br>
<input type="submit" value="アップロード">
</form>
</html>
form タグの method を post にし、enctype を multipart/form-data にすると、ファイルをアップロードすることができるんですね。このenctype="multipart/form-data"に関して素晴らしい記事を見つけたので、貼っておきます。
enctype='multipart/form-data'ってなんだ? - MUGENUP技術ブログ
こういう記事大好きです。
(2-2-2) phpでデータ受信
upload.php
<?php
if (is_uploaded_file($_FILES["upfile"]["tmp_name"])) {
if (move_uploaded_file($_FILES["upfile"]["tmp_name"], "import/" . $_FILES["upfile"]["name"])) { chmod("import/" . $_FILES["upfile"]["name"], 0777);
echo $_FILES["upfile"]["name"] . "をアップロードしました。”;
} else {
echo "ファイルをアップロードできません。”; }
} else {
echo "ファイルが選択されていません。”;
}
?>
php不慣れなので以下に訳しました。
(訳) is_uploaded_file関数で、ファイルがアップロードされたか確かめよ。これができなかったら、「ファイルが選択されていません」と表示せよ。mova_uploaded_file関数で、一時的にサーバー上に保存されたファイルを、importという名前のフォルダに移し、オリジナルのファイル名で保管せよ。chmod関数でパーミッションの管理を777に指定せよ。以上がうまくいかなかったら、「ファイルをアップロードできない」と表示せよ。
以上で無事、ブラウザ上からファイルをアップロードできるようになりました。
(3) 簡略化2について
(3-1) 参考サイト
(3-2) やったこと
シェルスクリプト実行用のデモファイルを作りました。
index.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test shell</title>
</head>
<body>
<h1>シェルスクリプト実行</h1>
<?php
$output = shell_exec("sh ./sample.sh");
?>
</body>
</html>
このページを開くと、ちゃんとシェルスクリプトが実行されていました。
(4) 簡略化3について
(4-1) 参考サイト
readfile: ファイルを出力する (ファイルシステム 関数)
(4-2) やったこと
こちらも(3)同様、デモファイルを作りました。
export.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>export test</title>
</head>
<body>
<h1>ファイルをダウンロードします。</h1>
<?php
$file = 'export/sample.csv';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary'); header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
?>
</body>
</html>
できました。よっしゃー!
(4) 簡略化4について
あとはこれら3つを1つにまとめる作業です。さらにもう一つやらないといけないことが...指定するファイル名の変数化です。どういうことかと言うと、
・a.csvが指定されたら、a.shシェルスクリプトが実行されて、aexp.csvが出力される
・b.csvが指定されたら、b.shシェルスクリプトが実行されて、bexp.csvが出力される
・c.csvが指定されたら、c.shシェルスクリプトが実行されて、cexp.csvが出力される
このa, b, cの部分を変数化したいという訳です。
ファイル名は、$_FILES["upfile"]["name"]で取得できますが、これをechoすると、
a.csv
.csvまで取得されてしまいます。ここを消したいので、
$filename=$_FILES["upfile"]["name"];
$cut=4;
$replace = substr($filename , 0 , strlen($filename)-$cut);
と書きました。(参考: [PHP] 文字列の前後から指定した数の文字を削除する)
今回これを実装できたことが一番嬉しかったです!
あとは、1つにまとめる作業ということで、index.htmlから情報を渡すupload.phpを次のように書きました。
upload.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>sample</title>
</head>
<body>
<p>
<?php
if (is_uploaded_file($_FILES["upfile"]["tmp_name"])) {
if (move_uploaded_file($_FILES["upfile"]["tmp_name"], "import/" .
$_FILES["upfile"]["name"]))
{ chmod("import/" . $_FILES["upfile"]["name"], 0777);
echo $_FILES["upfile"]["name"] . "をアップロードしました。";
$filename=$_FILES["upfile"]["name"];
$cut=4;
$replace = substr($filename , 0 , strlen($filename)-$cut);
$output = shell_exec("sh shell/".$replace."import.sh");
$file = 'export/'.$replace.'export.csv';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
} else {
echo "ファイルをアップロードできません。";
}
} else {
echo "ファイルが選択されていません。";
}
?>
</p>
</body>
</html>
実装キタ━━━━(゚∀゚)━━━━!!
めちゃくちゃ嬉しかったです。
自分がこのようなGUIを作れるようになるなんて夢のようでした。
書いたコードが正常に動き出すのは、最高に気持ちがいいです!
これからもプログラミングの勉強頑張ります!