- 投稿日:2020-07-04T22:30:56+09:00
【PHP】バリデーション(半角英字・郵便番号・メールアドレス)
プログラミング初学者がアウトプットのため気まぐれ更新。
アドバイス等あればご教示頂きたく、よろしくお願い致します。よく使うバリデーションをキロクしておきます。
半角英字
ユーザー名の登録などで使用する。
{ }
のなかに数字をいれることで、文字数制限もできる。validation.php// 半角英字であるかチェック $pattern ='/^[a-zA-Z]+$/'; // 8文字以内の半角英数字であるかチェック $pattern ='/^[a-zA-Z0-9]{8}+$/';郵便番号
validation.php// 郵便番号であるかチェック $pattern ='/[0-9]{3}-[0-9]{4}/';メールアドレス
validation.php// メールアドレスであるかチェック $pattern ='/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/iD';
お問い合わせフォームでよく使うバリデーションをまとめました。
ありがとうございます。
- 投稿日:2020-07-04T22:30:56+09:00
【PHP】正規表現(半角英字・郵便番号・メールアドレス)
プログラミング初学者がアウトプットのため気まぐれ更新。
アドバイス等あればご教示頂きたく、よろしくお願い致します。今回は、よく使う正規表現をキロクしておきます。
半角英字
ユーザー名の登録などで使用する。
{ }
のなかに数字をいれることで、文字数制限もできる。validation.php// 半角英字であるかチェック $pattern ='/^[a-zA-Z]+$/'; // 8文字以内の半角英数字であるかチェック $pattern ='/^[a-zA-Z0-9]{8}+$/';郵便番号
validation.php// 郵便番号であるかチェック $pattern ='/[0-9]{3}-[0-9]{4}/';メールアドレス
validation.php// メールアドレスであるかチェック $pattern ='/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/iD';
お問い合わせフォームでよく使う正規表現をまとめました。
ありがとうございます。
- 投稿日:2020-07-04T19:06:53+09:00
PHPでAWS S3 の大きいファイルの読込
やりたいこと
- amazon s3 から大きめのファイルをダウンロードしたい
- いちどに取得しよとすると大変そうなので少しずつ取得したい。
- PHP で取得を行う
接続情報を準備する
define('S3', [ 'KEY' => AWSのS3のKEYを設定する, 'PASS' => AWSのS3のパスワードを設定する, 'DIR' => AWSのS3のディレクトリを設定する(s3://<bucket>[/<key-or-prefix>])) ]);接続を行う
AWS SDK for PHP
を使用して接続するAmazon S3 ストリームラッパー
を使用して接続操作を行うrequire_once 'aws/vendor/autoload.php'; // S3 接続を行う $s3 = S3Client::factory([ 'credentials' => [ 'key' => S3['KEY'], 'secret' => S3['PASS'], ], 'region' => 'ap-northeast-1', 'version' => 'latest', ]); $s3->registerStreamWrapper();
- 関数は
registerStreamWrappe
を使用するregisterStreamWrapper
を使用すると、ファイルの操作と同じく S3 にアップされているファイルを操作できる。操作を行う
- たとえば、指定しファイルがあるか確認を行う
$readFileName = S3['DIR'].'/確認したいファイル名.XX'; if(file_exists($readFileName)) { echo 'ファイルあり'; }
- たとえば、
fread
を使用して読み込みを行う$readFileName = S3['DIR'].'/読み込みたいファイル名.XX'; $fp = fopen($readFileName, "r"); while(!feof($fp)) { $file = fread($fp, 4096); } close($fp);
- 上記のことからわかるように、接続後一般的なファイル操作で S3 のファイルを操作できる。
- 投稿日:2020-07-04T15:15:21+09:00
Laravel シンボリックリンクが切れた時の復旧方法
Laravel のStorage を使っていて、シンボリックリンクが切れてファイルの読み込みができなくなる時があります。
その時の復旧方法を備忘録的に残します。
シンボリックリンクの設定
php artisan storage:linkこれでシンボリックリンクの設定ができます。
Storage フォルダがroot直下にでき、/public 直下からリンクが張られます。
それでうまくいっていたはずが、色々やるうちに変わったり外れてしまった場合の対処法です。
シンボリックリンクの確認
ローカルの場合、仮想環境のサーバにログインします。
プロジェクトのフォルダまで移動し、ls -la でシンボリックリンクを確認します。
vagrant@homestead:~/code/project$ cd public vagrant@homestead:~/code/project/public$ ls -la total 24 drwxr-xr-x 1 vagrant vagrant 384 Jul 4 02:52 . drwxr-xr-x 1 vagrant vagrant 960 Jun 28 07:37 .. drwxr-xr-x 1 vagrant vagrant 96 Jun 16 11:26 css -rw-r--r-- 1 vagrant vagrant 6148 May 15 06:23 .DS_Store -rw-r--r-- 1 vagrant vagrant 0 Apr 10 07:56 favicon.ico -rw-r--r-- 1 vagrant vagrant 603 Apr 10 07:56 .htaccess -rw-r--r-- 1 vagrant vagrant 1823 Apr 10 07:56 index.php drwxr-xr-x 1 vagrant vagrant 96 Jun 16 11:26 js -rw-r--r-- 1 vagrant vagrant 71 Jun 28 07:38 mix-manifest.json -rw-r--r-- 1 vagrant vagrant 24 Apr 10 07:56 robots.txt lrwxr-xr-x 1 vagrant vagrant 45 Jul 4 02:52 storage -> /User/hogehoge/code/project/storage/app/public/ drwxr-xr-x 1 vagrant vagrant 128 May 15 08:02 voice仮想環境なのに /User/hogehoge/code/project/storage/app/public/ みたいなパスになっていたら間違いです。
シンボリックリンクを削除する
リンクが間違っていたら、unlink でリンクを削除します。
vagrant@homestead:~/code/project/public$ unlink storage正しいパスでシンボリックリンクを設定する
シンボリックリンクの設定は ln -s [正しいパス] [storage] です。
正しいパスは、$pwd でプロジェクトrootのパスを確認し、/project/storage/app/public/ を設定。
vagrant@homestead:~/code/project/public$ ln -s /home/vagrant/code/project/storage/app/public/ storageついでに: 本番環境でシンボリックリンクが繋がらないとき
単純に繋がっていないだけのことが多いので、サーバにログインして、storage:link しましょう。
php artisan storage:link参考
- 投稿日:2020-07-04T14:55:21+09:00
PHP入門 - お問い合わせフォームを作ろう (1)
PHPを持っていない方は事前にインストールしておいてください。
フォーム画面の作成
任意のディレクトリにindex.phpを作成します。
index.php<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>お問合せフォーム</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> </head> <body> <div class="container"> <form action="" method="POST"> <h4 class="py-4 text-center">お問い合わせ</h4> <div class="form-group"> <div class="row justify-content-center"> <div class="col-md-8 col-offset-2"> <label for="inputName">お名前(必須)</label> </div> <div class="col-md-8 col-offset-2"> <input type="text" name="name" id="inputName" class="form-control rounded-0" required autofocus> <p class="error_msg text-danger">※お名前をご記入下さい</p> </div> </div> </div> <div class="form-group"> <div class="row justify-content-center"> <div class="col-md-8 col-offset-2"> <label for="inputEmail">メールアドレス(必須)</label> </div> <div class="col-md-8 col-offset-2"> <input type="email" name="email" id="inputEmail" class="form-control rounded-0" required> <p class="error_msg text-danger">※メールアドレスをご記入下さい</p> </div> </div> </div> <div class="form-group"> <div class="row justify-content-center"> <div class="col-md-8 col-offset-2"> <label for="inputContent">お問い合わせ内容(必須)</label> </div> <div class="col-md-8 col-offset-2"> <textarea name="contact" id="inputContent" rows="10" class="form-control rounded-0" required></textarea> <p class="error_msg text-danger">※お問い合わせ内容をご記入下さい</p> </div> </div> </div> <div class="row justify-content-center"> <div class="col-md-8 col-offset-2"> <button type="submit" class="btn btn-primary w-100 rounded-0">確認画面へ</button> </div> </div> </form> </div> </body> </html>ブラウザで確認すると、下の画面のようになっているのがわかります。
入力チェック
サーバ側で入力チェックをするために、novalidateを追加します。
index.php<form action="" method="POST" novalidate> // 追記次に<!DOCTYPE>の上にPHPのコードを書いていきます。
index.php<?php if ($_SERVER['REQUEST_METHOD'] === 'POST') { $post = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING); if ($post['name'] === '') { $error['name'] = 'blank'; } } ?>名前が未入力のとき、変数名$errorに'blank'という値が入るようにします。
そして、名前入力欄に下記のコードを追加します。index.php<input type="text" name="name" id="inputName" class="form-control rounded-0" required autofocus> // ここから <?php if ($error['name'] === 'blank'): ?> <p class="error_msg text-danger">※お名前をご記入下さい</p> <?php endif; ?> // ここまでブラウザを更新します。すると、
名前入力欄の下に表示されていたエラーメッセージが消えました。
空欄のまま「確認画面へ」ボタンを押してみてください。「※お名前をご記入ください」というエラーメッセージが表示されるはずです。
これで名前の入力チェックは完了です。入力していた文字をそのまま残す
今の状態で「確認画面へ」ボタンを押すと、エラー時に入力していた文字が消えてしまいます。そこで、value属性を追加します。
index.php<input type="text" name="name" id="inputName" class="form-control rounded-0" value="<?php echo htmlspecialchars($post['name']); ?>" required autofocus>これでエラーになっても直前に入力していた文字が消えずに残るようになりました。
この調子で、メールアドレスとお問い合わせ内容を編集していきます。
index.phpの内容は下記の通りになります。
index.php<?php $error = []; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $post = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING); if ($post['name'] === '') { $error['name'] = 'blank'; } if ($post['email'] === '') { $error['email'] = 'blank'; } if ($post['contact'] === '') { $error['contact'] = 'blank'; } } ?> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>お問合せフォーム</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> </head> <body> <div class="container"> <form action="" method="POST" novalidate> <h4 class="py-4 text-center">お問い合わせ</h4> <div class="form-group"> <div class="row justify-content-center"> <div class="col-md-8 col-offset-2"> <label for="inputName">お名前(必須)</label> </div> <div class="col-md-8 col-offset-2"> <input type="text" name="name" id="inputName" class="form-control rounded-0" value="<?php echo htmlspecialchars($post['name']); ?>" required autofocus> <?php if ($error['name'] === 'blank'): ?> <p class="error_msg text-danger">※お名前をご記入下さい</p> <?php endif; ?> </div> </div> </div> <div class="form-group"> <div class="row justify-content-center"> <div class="col-md-8 col-offset-2"> <label for="inputEmail">メールアドレス(必須)</label> </div> <div class="col-md-8 col-offset-2"> <input type="email" name="email" id="inputEmail" class="form-control rounded-0" value="<?php echo htmlspecialchars($post['email']); ?>" required> <?php if ($error['email'] === 'blank'): ?> <p class="error_msg text-danger">※メールアドレスをご記入下さい</p> <?php endif; ?> </div> </div> </div> <div class="form-group"> <div class="row justify-content-center"> <div class="col-md-8 col-offset-2"> <label for="inputContent">お問い合わせ内容(必須)</label> </div> <div class="col-md-8 col-offset-2"> <textarea name="contact" id="inputContent" rows="10" class="form-control rounded-0" required><?php echo htmlspecialchars($post['contact']); ?></textarea> <?php if ($error['contact'] === 'blank'): ?> <p class="error_msg text-danger">※お問い合わせ内容をご記入下さい</p> <?php endif; ?> </div> </div> </div> <div class="row justify-content-center"> <div class="col-md-8 col-offset-2"> <button type="submit" class="btn btn-primary w-100 rounded-0">確認画面へ</button> </div> </div> </form> </div> </body> </html>ブラウザを更新し、ご自身で動作確認をしてみてください。
メールアドレスのバリデーション
メールアドレスが書式通り(XXXXXX@XXX.XXX)になっているかどうかをチェックします。メールアドレスの条件式に追記します。
index.phpif ($post['email'] === '') { $error['email'] = 'blank'; } else if (!filter_var($post['email'], FILTER_VALIDATE_EMAIL)) { $error['email']= 'email'; }メールアドレス入力欄にエラーメッセージを追加します。
index.php<?php if ($error['email'] === 'email'): ?> <p class="error_msg text-danger">※メールアドレスを正しくご記入下さい</p> <?php endif; ?>ブラウザを更新し、動作確認をします。
正しく動作していることがわかります。これでメールアドレスの書式チェックは完了です。
確認画面への移動
コードを追加します。
index.php<?php $error = []; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $post = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING); if ($post['name'] === '') { $error['name'] = 'blank'; } if ($post['email'] === '') { $error['email'] = 'blank'; } else if (!filter_var($post['email'], FILTER_VALIDATE_EMAIL)) { $error['email']= 'email'; } if ($post['contact'] === '') { $error['contact'] = 'blank'; } // ここから if (count($error) === 0) { header('Location: confirm.php'); exit(); } // ここまで } ?>これで「確認画面へ」ボタンを押すと、入力した内容に問題がなければconfirm.phpにページが移動します。
まだconfirm.phpを作成していないので、作成しましょう。index.phpの中身をほとんどそのままコピペした内容になっています。
confirm.php<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>送信内容確認</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> </head> <body> <div class="container"> <form action="./confirm.php" method="POST"> <h4 class="py-4 text-center">確認画面</h4> <div class="form-group"> <div class="row justify-content-center"> <div class="col-md-8 col-offset-2"> <label for="inputName">お名前(必須)</label> </div> <div class="col-md-8 col-offset-2"> <p>テスト</p> </div> </div> </div> <div class="form-group"> <div class="row justify-content-center"> <div class="col-md-8 col-offset-2"> <label for="inputEmail">メールアドレス(必須)</label> </div> <div class="col-md-8 col-offset-2"> <p>test@test.com</p> </div> </div> </div> <div class="form-group"> <div class="row justify-content-center"> <div class="col-md-8 col-offset-2"> <label for="inputContent">お問い合わせ内容(必須)</label> </div> <div class="col-md-8 col-offset-2"> <p>テスト</p> </div> </div> </div> <div class="row justify-content-center"> <div class="col-md-8 col-offset-2"> <a href="index.php" class="btn btn-primary rounded-0">戻る</a> <button type="submit" class="btn btn-primary rounded-0">送信する</button> </div> </div> </form> </div> </body> </html>これでindex.phpからconfirm.phpにページが移動できるようになりました。
現時点では、index.phpで記入した内容はconfirm.phpに反映されていません。
次回はセッションを有効にし、ページをまたいでも値が保持できるようにしましょう。
- 投稿日:2020-07-04T14:52:03+09:00
Laradock でLaravel + SQLServerの環境を用意する
Laradockの取得
基本は 公式ドキュメント を参照
// 作業用ディレクトリにlaradockをクローンする git clone https://github.com/Laradock/laradock.git // envファイルをコピーする cd laradock cp env-example .env本記事は公式ドキュメントの新規作成用のプロジェクト手順に従い、次のディレクトリ構成となる想定です。
作業用フォルダ ├ laradock └ lara-test(新規プロジェクトフォルダ)dockerをビルドする前に行う設定
.envの修正
基本設定
APP_CODE_PATH_HOST
に作成予定のプロジェクト名を入力するAPP_CODE_PATH_HOST=../lara-test/SQL Server用設定
DB名、SA用パスワード、ポート番号を設定する。
パスワードは8文字以上で大文字小文字記号数字の4種類から3種以上含んでいる必要があります。パスワード ポリシー### MSSQL ################################################# MSSQL_DATABASE=master MSSQL_PASSWORD="yourStrong(!)Password" MSSQL_PORT=1433WORKSPACE用のインストールオプション、PHP_FPM用のインストールオプションをtrueに変更する。
### WORKSPACE ############################################# WORKSPACE_INSTALL_MSSQL=true ### PHP_FPM ############################################### PHP_FPM_INSTALL_MSSQL=trueそれぞれtrueにしないとDB接続時に次のようなエラーが発生します。
Illuminate\Database\QueryException could not find driverdocker-compose.ymlの修正
ボリュームコンテナーを使用するための修正(Macでのみ必須)
デフォルトでは
${DATA_PATH_HOST}
のディレクトリにマウントするように設定されていますが、Macの場合はそのままだとエラーが出ます。エラー内容2020-05-08 06:49:33.62 Server Error: 17113, Severity: 16, State: 1. 2020-05-08 06:49:33.62 Server Error 87(パラメーターが間違っています。) occurred while opening file '/var/opt/mssql/data/master.mdf' to obtain configuration information at startup. An invalid startup option might have caused the error. Verify your startup options, and correct or remove them if necessary.2020年6月時点ではMac上ではホストのディレクトリマウントがサポートされていないためです。
https://docs.microsoft.com/ja-jp/sql/linux/sql-server-linux-configure-docker?view=sql-server-ver15#mount-a-host-directory-as-data-volume現時点では、SQL Server on Linux イメージを使用した Mac 上の Docker のホスト ボリューム マッピングはサポートされていません。 代わりにデータ ボリューム コンテナーを使用してください。
回避するためにはデータボリュームコンテナを用意してそちらを使用する必要があります。
volume定義例volumes: mssqlvolume: driver: localvolumes: # - ${DATA_PATH_HOST}/mssql:/var/opt/mssql - mssqlvolume:/var/opt/mssqlインストール時に使用される環境変数の変更
設定可能な環境変数はこちら
### MSSQL ################################################ mssql: build: context: ./mssql environment: - MSSQL_PID=Express - MSSQL_DATABASE=${MSSQL_DATABASE} - SA_PASSWORD=${MSSQL_PASSWORD} - ACCEPT_EULA=YDeveloperエディションにするなら
MSSQL_PID=Developer
に変更、言語を日本語にしたいならMSSQL_LCID=1041
に変更など。以降は基本的にMySQLの場合などと同様。
失敗したら、画面に表示されるエラーログやdokcer logs
でログを確認する。コンテナを立ち上げてプロジェクトを作成する
docker-compose up -d workspace nginx mssql php-fpmでコンテナをビルド & 立ち上げて
docker-compose exec workspace bashでコンテナに入って
composer create-project --prefer-dist laravel/laravel .でプロジェクトを作成する。
コンテナ上では/var/www
下にファイルが配置され、ホストPC上ではAPP_CODE_PATH_HOST
で設定したプロジェクトフォルダに各ファイルが配置されている状態となります。コンテナ上にLaravelのファイルが作成される/var/www# ls -a . artisan composer.lock .editorconfig .gitattributes phpunit.xml resources storage vendor .. bootstrap config .env .gitignore public routes .styleci.yml webpack.mix.js app composer.json database .env.example package.json README.md server.php testsこの状態で http://localhost を開くとlaravelのデフォルトページが表示されることが確認できます。
Laravel側のDB設定と疎通確認
Laravel用の.envでSQL Server用の設定をする
新規作成されたlaravelのプロジェクトの.envを編集
DB_CONNECTION=sqlsrv DB_HOST=laradock_mssql_1 DB_PORT=1433 DB_DATABASE=master DB_USERNAME=SA DB_PASSWORD='""yourStrong(!)Password""'
docker-compose.yml
のデフォルトのパスワードではダブルクォートが入っていますが、そのまま.env
に記載すると除外されてしまうので、上記のような対応が必要です。疎通確認
routes/web.php
にRoute::get('/test/', function () { return json_encode(\Illuminate\Support\Facades\DB::select("select @@version")); });を追加して、 http://localhost/test/ でSQL Serverのバージョン情報が表示されたらSQL Serverに接続ができています。
- 投稿日:2020-07-04T13:37:25+09:00
会員制ライブ動画配信サイトの骨組をAWSで作ろう
こんにちは?
今日は、タイトルのことを↓のような方法で実現してみます。
- S3にHLS動画を置く。パブリックアクセスは許可しない。
- CloudFront経由でのみ、その動画を再生できるようにする。
ただし再生にはCloudFrontの暗号鍵で署名したCookieが必要となるよう設定する。- CloudFrontにドメインを割り当てる。
- AWS SDKのCloudFrontクライアントが使えて署名Cookieを操作できる言語(本記事ではPHP)で、動画配信WEBアプリケーションを作る。
- WEBサーバーに、CloudFrontとセカンドレベルドメインまで同じドメインを割り当てる。
またCloudFrontの暗号鍵を持たせる。(これでCloudFrontとWEBサーバーで署名Cookieを共有できる)- あとは署名Cookie発行をWEBアプリケーションの業務ロジックでコントロールすれば、会員制動画配信が実現可能!(これ以降は本記事では割愛します。)
ついでにCORS対応を施して、
Safari以外のブラウザ(本記事ではChrome)でHLS動画再生も実現します。
正味作業時間はそれほどかかりませんでしたが、
- つまづきポイントが多い
- 回避不能な待ち時間が発生する
関係でブヒブヒ言うハメになったので、スクリーンショット付きで詳しく説明していきます。
結構長いですが、お付き合いくださいませ...。おことわり
本記事中のAWSリソースなどは執筆のために一時的に作成したものです。
流用はできませんので、あしからずご了承くださいませ。必要なもの
AWSアカウント。
ドメイン取得などを実施するので若干料金が発生します。2,000円くらいあれば十分。
またドメイン名を何にするか決めておくとスムーズです。
(本記事の例ではyagrush.net
にしています。)シェルが使えてHLS動画が再生できる端末(Macおすすめ。)
Docker & docker-compose(Docker Desktopならdocker-composeも付いてくるので、おすすめ。)
Chrome
HLS(HTTP Live Streaming)とは
Appleさんが作った動画配信技術。
AbemaTVとかでも使われてるそうです。
本記事ではこのHLSを使っていきます。昨今の事情に合ったメリットがいっぱいあります。
- HTTPと相性が良く、一般的なWEBサーバーで動画配信できる。
- 再生品質をリアルタイム変更できるので安定して配信しやすい。
- 暗号や認証対応が充実。
etc...Safariが一番相性良いですが、他ブラウザでも再生方法はあります。
(後のほうで説明します。)HLSの動画ファイル形式
.ts
と.m3u8
という拡張子の2種類のファイルで構成されます。
(.mp4 から変換してくれるソフトやオンラインサービスがいっぱいあります。)
.ts
ファイル動画データファイル。
1本の動画を数秒単位で細切れにしたもの。
HLS動画はこの .ts ファイル何百何千個で構成されており、しかもそれが再生品質パターン分あったりする。
.m3u8
ファイルHLS動画ファイルのメイン。
山ほどある .ts のファイルパスや再生する順番が記録されている。ちなみに他の.m3u8ファイルを入れ子にもできる。
例えば、低品質用 .m3u8 にサッと挿げ替えれば、動画再生を止めずに再生品質を下げれたり。本物のライブ配信システムは .ts をリアルタイムでガシガシ作成していき .m3u8 をガンガン書き換えることで実現しているそうです。
作業開始
.m3u8ファイルと.tsファイルを用意する
いきなり言われても大変ですよね。
そこで、こちらのサイトで公開されているサンプルHLS動画ファイルをお借りします。
すごく使いやすかったので。(もし怒られたら、差し替えします…。)再生品質400K, 2K, 4Kそれぞれ Tears00000~00010.ts の計10個ずつあれば10秒ほど再生できます。
動作確認には十分。※ 全編だと恐らく.tsファイルが数千個以上あります。
迷惑をかけるので、無理なダウンロードはやめましょう!.m3u8
https://tech.jstream.jp/analytics/ex0/all-tears.m3u8
https://tech.jstream.jp/media/ToS/400K/Tears.m3u8
https://tech.jstream.jp/media/ToS/2K/Tears.m3u8
https://tech.jstream.jp/media/ToS/4K/Tears.m3u8.ts(400K)
https://tech.jstream.jp/media/ToS/400K/Tears00000.ts
https://tech.jstream.jp/media/ToS/400K/Tears00001.ts
~
https://tech.jstream.jp/media/ToS/400K/Tears00009.ts
https://tech.jstream.jp/media/ToS/400K/Tears00010.ts.ts(2K)
https://tech.jstream.jp/media/ToS/2K/Tears00000.ts
https://tech.jstream.jp/media/ToS/2K/Tears00001.ts
~
https://tech.jstream.jp/media/ToS/2K/Tears00009.ts
https://tech.jstream.jp/media/ToS/2K/Tears00010.ts.ts(4K)
https://tech.jstream.jp/media/ToS/4K/Tears00000.ts
https://tech.jstream.jp/media/ToS/4K/Tears00001.ts
~
https://tech.jstream.jp/media/ToS/4K/Tears00009.ts
https://tech.jstream.jp/media/ToS/4K/Tears00010.tstsファイル00000~00010を一発ダウンロードするシェルの例.悪用しないでね!URLBASE=https://tech.jstream.jp/media/ToS/400K mkdir -p media/ToS/400K cd media/ToS/400K wget $URLBASE/Tears.m3u8 for i in `seq 0 10` do fileno=`printf %05d $i` wget $URLBASE/Tears$fileno.ts if [ $? -gt 0 ]; then exit 99 fi done cd ../..S3作業
S3は動画ファイル置き場です。
CloudFront経由かつ特定ドメインからの再生 のみアクセスできるよう、設定を施します。まずはバケットを作る
CloudFront経由でアクセスするので、パブリックアクセス許可は不要です。
HLS動画ファイルをS3にアップロード
サンプル動画の.m3u8に合わせたディレクトリ構造でアップロードしてください。
S3バケット/ all-tears.m3u8 media/ ToS/ 400K/ Tears.m3u8 Tears00000.ts ... Tears00010.ts 2K/ Tears.m3u8 Tears00000.ts ... Tears00010.ts 4K/ Tears.m3u8 Tears00000.ts ... Tears00010.tsCloudFront作業
ここで一旦、CloudFrontの作業に移ります。
CloudFrontは、S3の門番役です。
特定アクセスのみ動画データを転送するよう、色々設定します。CloudFrontディストリビューション作成
以下の設定だけを変更して、
設定項目名 値 Origin Domain Name クリックするとドロップリストが出るので、先ほど作成したS3を選んでください。 Origin ID ドロップリストを選択すれば自動的にセットされると思います。 Ristrict Buchet Access YESを選んでください。 Whitelist Headers 左のリストからOriginを選択して【Add >>】ボタンを押し、右のリストにOriginが移動するようにしてください。 Ristrict Viewer Access YESを選んでください。 それ以外は触らないでOKです。
最後に【Create Distribution】ボタンを押してください。CloudFrontディストリビューションが作成されます。
ちなみにID(本例ではERDBXHEEWQCAE
)をクリックすると詳細画面に遷移できます。S3がCloudFrontからのアクセスを許可するのに必要な情報を調べる
Origin Access Identityという値を調べます。
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.htmlこれはCloudFrontがS3にアクセスするための特別なユーザーで、ディストリビューション作成したときに自動的に作成されているはずです。
これのIDを控えておいてください。
欄がせまくて途中で見切れていますが、ダブルクリックで全選択→クリップボードなどで確実に控えましょう。再びS3作業
バケットポリシーを設定する
S3のバケットポリシー設定画面を開きます。
テキストボックスに↓のJSONコードをコピペしてください。
ただし2箇所、あなたの環境に合わせて変更する必要があります。{ "Version": "2012-10-17", "Statement": [ { "Sid": "Grant a CloudFront Origin Identity access", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E1DCCPJY6X9NYO" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::yagrush-hls/*" } ] }
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity
のあとに、さきほどコピーしたCFディストリビューションのOrigin Access IdentityのIDを貼り付けてください。"Resource": "arn:aws:s3:::
のあとに、あなたが作成したS3のバケット名/*
を貼り付けてください。最後に【保存】ボタンを押してください。
エラーが表示されなければOK。CORS構成を設定する
CORSとは
異なるサーバー間でリソース(動画とか)を共有できるようにする仕組みです。
これをちゃんと設定しないと、Safari以外のブラウザではS3に置かれたHLS動画を再生できません。
ある意味クロスサイトスクリプティングみたいなことになってしまい、エラーになります。ちなみにSafariだけは(HLSを開発したAppleさんだけあって)ダイレクトにプラグインが起動してあっけなく再生できてしまいます。
設定する
S3バケットの【アクセス権限】タブから【CORSの設定】画面を開きます。
↓のXMLをコピペして下さい。
ただ1ヶ所、変更して頂く必要があります。<?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>http://web.yagrush.net:8000</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <AllowedMethod>HEAD</AllowedMethod> <MaxAgeSeconds>3000</MaxAgeSeconds> <AllowedHeader>*</AllowedHeader> </CORSRule> </CORSConfiguration>
<AllowedOrigin>
の中のhttp://web.yagrush.net:8000
は、みなさんの環境に合わせて書き換えてください。(トップレベルとセカンドレベルドメイン(本例ではyagrush.net
)の部分は、予め決めたものから変えないで下さいね。)またこの値は、後ほど構築するWEBサーバーのURLに使用するので控えておいてください。
最後に【保存】ボタンを押して下さい。
エラーにならなければOK。※ XMLのタグを小文字にしたり、
<AllowedOrigin>
の値の末尾に/
が付いてたりするだけですぐエラーになります。かなりセンシティブなので、コピペや編集の際はご注意を。Route53作業
ドメインを取得する
ちょっと料金がかかります。
また、ここ、ウェイトポイントです!
購入したドメインが有効になるまで数時間かかる場合があります。では、AWSのRoute53にアクセスしましょう。
そして、ドメインを作成する画面まで進んでください。指定したドメインが世界でまだ使われていなければOK。
カートに入れて購入します。ドメイン購入は結構ウルサイです。
ちゃんと個人情報を入力しないといけません。
(※ 一度買ったことがあれば、この手順は発生しないと思います。)その後も「規約に同意しろ」とか色々質問が出ますが、ここでは説明は省略します。
無事購入すると、世界中に浸透させる処理が開始されます。これがまたリアル数時間かかります。
完了するとAWSからメールが来ると思うので、それまで休憩するのも良いでしょう。ドメインが有効になったら続きをやりましょう。
CloudFrontに振るサブドメインを決める
本例では
cf.
を付けてcf.yagrush.net
にしています。ドメインとCloudFrontを結びつける
Route53でCNAMEという設定を追加すると、そういうことができます。
別名を登録する感じです。その前にまずCloudFrontの画面で、CloudFrontディストリビューションのデフォルトアドレスを調べておきましょう。
↓このへんに表示されているやつですね。本例では
d14br4vlcj23gd.cloudfront.net
です。
※ またもや欄がせまくて途中で見切れているので、クリップボードコピーするときはご注意ください。Route53にCNAMEレコードを追加する
まずはRoute53の画面を辿って「レコードセットの作成」まで進んでください。
「レコードセットの作成」ボタンを押すと、画面右側に設定小窓が出るので、先ほど調べておいた情報を設定して【作成】ボタンを押します。
これでOK。
再びCloudFront作業へ
CloudFront用サーバー証明書を取得する
CloudFrontディストリビューションの詳細設定画面を開いてください。
中段あたりにある【Request or Import a Certificate with ACM】ボタンを押して下さい。
「証明書のリクエスト」画面が開きます。
まずこのとき、画面右上のリージョン表示が「東京」などではなく「バージニア北部」になっていることを確認してください。(CloudFrontのエンドポイントはバージニア北部にあるため、バージニア北部で取得した証明書じゃないと使えないそうです。罠ポイント。)それでは、先ほどのCloudFront用サブドメインを入力して【次へ】を押して下さい。
タグは、必要でしたらお好みで設定してください。
【確認】ボタンを押します。
なんだか不安にさせられる画面になりました...
でも大丈夫、【続行】を押して下さい。
こんな画面に遷移しました。
これまた不穏な...もちろんこのままではダメです。
画面中段あたり、CloudFront用ドメインの左にある ▼ を押して下さい。小窓が展開されます。
その中にあるボタン【Route53でのレコードの作成】を押して下さい。
はい、来ました!ここもウェイトポイントです!
証明書が使えるようになるまで数時間かかる場合があります...。
(わりとすぐの場合もあります。)完了すると↓に変わるはずです。
時間をおいてチェックしてみてください。
OKになったら作業の続きを。
CloudFrontに証明書をセットする
CloudFrontの詳細画面をまた開いてください。
中段あたりの
SSL Certificate
で、2番目の選択肢Custom SSL Certificate(example.com)
がアクティブになり選択できるようになっているはずです。
それを選択しましょう。※ たまに、証明書OKなのに選択肢
Custom SSL Certificate(example.com)
がアクティブになるまで時間がかかる場合があるようです...。そしてその下にあるボックスをクリックするとドロップリストが開き、先ほどの証明書が選択できます。
更にそれらより上の方、
Alternate Domain Names
にCloudFront用サブドメインを入力します。全部終わったら、一番右下の【Yes, Edit】ボタンを押しましょう。
問題なければ、前の画面にスッと戻るはずです。
(もしエラーだと、赤字で下の方に表示されます。)CloudFrontキーペアを作成する
今作業をしているAWSアカウントがルートアカウントでない場合、ログアウトしてルートアカウントでAWSコンソールにログインしなおしてください。(ルートアカウントじゃないとできない作業なのです。)
ルートアカウントで画面右上のユーザーメニューから「マイセキュリティ資格情報」を開きます。
ルートアカウントのみ【CloudFrontのキーペア】というタブが出現します。
それを開くと【新しいキーペアの作成】ボタンがあるので押して下さい。
こうなればOK。
- 【プライベートキーファイルのダウンロード】
- 【パブリックキーファイルのダウンロード】
は、ダウンロードしておいてください。
後で使います。後はもうルートアカウントじゃなくてOK。
WEBアプリケーションを作る
以上でAWS作業からは離れます。
次にDockerとPHPを使ってWEBアプリケーションを作りましょう。
動画配信サイトにあたる部分です。本記事ではローカルに構築して、hostsファイルを書き換えて対応します。
本格的にリモートに構築すると面倒なので...。hostsを編集する
WEBサーバーのURL(本例では
web.yagrush.net
)をローカル(127.0.0.1)に向けます。sudo vim /etc/hosts
/etc/hosts.127.0.0.1 localhost web.yagrush.netこれで
web.yagrush.net
のURLでアクセスするかぎり、HLS動画を再生できます。
CloudFrontをだます ...って言い方もアレですけどね。さすがに記事が辛くなってきた
あと少し...!WEBアプリケーション一式セットをダウンロードする
今回、動作確認済のWEBアプリケーション一式セットを予めご用意しました。
https://github.com/yagrush/hls-web
git clone
でもいいですが、ZIPダウンロード&解凍でもOK。
wgetコマンドが使える方は↓の一発コマンドをどうぞ。wget https://github.com/yagrush/hls-web/archive/master.zip -O hls-web.zip; unzip hls-web.zip; rm -f hls-web.zip #ついでにディレクトリを移動しておく cd hls-web-masterCloudFrontのプライベートキーファイルを配備する
前の方の手順でCloudFrontキーペアを作成してプライベートキーファイルをダウンロードしたと思います。
(こんな名前のファイルpk-XXXXXXXXXXXXXXXXXXX.pem
)
それをhls-web-master/backend/storage/app
に置いてください。設定をカスタマイズする
数か所、みなさんの環境に合わせて変更して頂く必要があります。
(一応目印として**hls**
というコメントを付けてあります。)
hls-web-master/backend/resources/views/play_video.blade.php
,hls-web-master/backend/app/Http/Controllers/PlayVideoController.php
cf.yagrush.net
やyagrush.net
の部分を、みなさんのケースに合わせて書き換えて下さい。
hls-web-master/backend/app/Http/Controllers/PlayVideoController.php
みなさんのCloudFrontキーペアのプライベートキーファイル名に合わせて
XXXXXXXXXXXXXXXXXXX
の部分を書き換えて下さい。
ちなみにキーペアIDも、プライベートキーファイル名のXXXXXXXXXXXXXXXXXXX
と同じです。hls-web-master/backend/resources/views/play_video.blade.php... ... var videoSrc = 'https://cf.yagrush.net/all-tears.m3u8'; //**hls** ... ...hls-web-master/backend/app/Http/Controllers/PlayVideoController.php... ... $resourceKey = "https://cf.yagrush.net/*"; //**hls** ... ... 'private_key' => storage_path() . '/app/pk-XXXXXXXXXXXXXXXXXXX.pem', //**hls** 'key_pair_id' => 'XXXXXXXXXXXXXXXXXXX' //**hls** ... ... $domain = 'yagrush.net'; //**hls** ... ...起動
hls-web-master/
で以下のコマンドを打ってください。(数分かかるかも。)make init問題なければ、
- ポート8000でnginxコンテナがWEBサーバーのフロントとして起動します。
- PHPを処理するためのバックエンドとしてphp-fpmコンテナが起動します。
- Laravelフレームワークのためだけにポート3306でmysqlコンテナが起動しますが、気にしないでください。
もしポート被りで起動に失敗したら、
hls-web-master/docker-compose.yml
を編集してポートを変更するなどしてくださいね。動画再生してみる
動画再生ページにChromeでアクセスしてみて下さい。
(本例だと http://web.yagrush.net:8000/play_video )再生されましたでしょうか?
↓こんな感じ。今回は動画データの一部だけしか配備してないので、10秒ほどで停止します。
お時間あればSafariでもアクセスしてみて下さい。
ちなみにSafari以外での再生のために hls.js を採用しました。動画に直アクセスできないのを確認してみる
以下のコマンドでcookieを使わずにアクセスしてみます。
(例によってyagrush.net
はみなさんの環境に合わせて書き換えて下さいね。)まずはOriginヘッダを付けて送信してみます。
curl -X GET -H 'Origin: http://web.yagrush.net:8000' -i -v -f https://cf.yagrush.net/all-tears.m3u8403エラー!
拒否されちゃいました。Note: Unnecessary use of -X or --request, GET is already inferred. * Trying xxx.xxx.xxx.xxx... * TCP_NODELAY set * Connected to cf.yagrush.net (xxx.xxx.xxx.xxx) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/ssl/cert.pem CApath: none * TLSv1.2 (OUT), TLS handshake, Client hello (1): * TLSv1.2 (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (IN), TLS handshake, Server key exchange (12): * TLSv1.2 (IN), TLS handshake, Server finished (14): * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.2 (OUT), TLS handshake, Finished (20): * TLSv1.2 (IN), TLS change cipher, Change cipher spec (1): * TLSv1.2 (IN), TLS handshake, Finished (20): * SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256 * ALPN, server accepted to use h2 * Server certificate: * subject: CN=cf.yagrush.net * start date: Jul 3 00:00:00 2020 GMT * expire date: Aug 3 12:00:00 2021 GMT * subjectAltName: host "cf.yagrush.net" matched certs "cf.yagrush.net" * issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon * SSL certificate verify ok. * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 * Using Stream ID: 1 (easy handle 0xxxxxxxxxxxxx) > GET /all-tears.m3u8 HTTP/2 > Host: cf.yagrush.net > User-Agent: curl/7.64.1 > Accept: */* > Origin: http://web.yagrush.net:8000 > * Connection state changed (MAX_CONCURRENT_STREAMS == 128)! * The requested URL returned error: 403 * stopped the pause stream! * Connection #0 to host cf.yagrush.net left intact curl: (22) The requested URL returned error: 403 * Closing connection 0今度はプライベートキーファイルまで付けて送信してみます。
curl -X GET -H 'Origin: http://web.yagrush.net:8000' -i -v -f -E backend/storage/app/pk-XXXXXXXXXXXXXXXXXX.pem https://cf.yagrush.net/all-tears.m3u8やはり怒られました。
Note: Unnecessary use of -X or --request, GET is already inferred. * Trying xxx.xxx.xxx.xxx... * TCP_NODELAY set * Connected to sample.flhls.net (xxx.xxx.xxx.xxx) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * could not load PEM client certificate, LibreSSL error error:09FFF06C:PEM routines:CRYPTO_internal:no start line, (no key found, wrong pass phrase, or wrong file format?) * Closing connection 0 curl: (58) could not load PEM client certificate, LibreSSL error error:09FFF06C:PEM routines:CRYPTO_internal:no start line, (no key found, wrong pass phrase, or wrong file format?)終了
以下のコマンドでWEBアプリケーションを終了&破棄します。
make destroyおつかれさまでしたぁーー!!!
WEBアプリケーション変更点 まとめ
今回は、定番のこちら -> 最強のLaravel開発環境をDockerを使って構築する【新編集版】 をベースに以下の手を加えました。
★ PHP用AWS SDKインストールをビルド工程(Makefile @ create-project)に追加。
docker-compose exec app composer require aws/aws-sdk-php
★ CloudFrontキーペアのプライベートキーファイルを
backend/storage/app
に配備。★
backend/routes/web.php
にルーティング設定追記。Route::get('/play_video', 'PlayVideoController@show');★ ソースコード2つ作成。
- backend/app/Http/Controllers/PlayVideoController.php
- backend/resources/views/play_video.blade.php
CloudFront+S3+Video.js+ 署名付きCookieでクローズドな動画配信 を参考に書きました。
↑お時間あれば是非ご覧になってみて下さい。参考文献
今回はこれらのサイトにお世話になりました。
ありがとうございます。
- 投稿日:2020-07-04T11:17:28+09:00
新人3ヶ月エンジニアが学んだPHP関数
新人3ヶ月エンジニアが学んだPHP関数
スクールでRailsを学び、晴れWebエンジニアになった私ですが
使用するフレームワークはLarabel 言語はPHPでした。
プロゲートでPHPを一周やって、あとはLaravelを触り続ける毎日で実務に突入したのですが
PHP関数は「ナンモワカラン」状態で、コードを読むのが大変だったので備忘録的に実務で使用していたPHP関数をまとめて置きたいと思います。array_column()
array_column(配列, ‘カラム名’, ‘カラム名’)配列から単一のカラムの値を返す
array_values ()
array_values ( 配列 )配列から全ての値を取り出し、数値添字をつけた配列を返します。
array_unique()
array_unique ( array $array [, int $sort_flags = SORT_STRING ] ) : array配列から重複した値を削除する
array_merge()
array_merge([配列],$配列)ひとつまたは複数の配列を結合する
array_search
array_search(検索ワード、検索配列)指定した値を配列で検索し、見つかった場合に対応する最初のキーを返す
strpos()
strpos(検索文字列、検索ワード、検索開始位置)文字列内の部分文字列が最初に現れる場所を見つける
curl_init()
$curl = curl_init();新しい cURL リソースを作成します
curl_setopt_array()
curl_setopt_array($curl, $options);CURL 転送用の複数のオプションを設定する
curl_exec($curl)
$result = curl_exec($curl);指定した cURL セッションを実行します。
curl_close($curl)
curl_close($curl);cURL セッションを閉じる
implode()
implode ( 文字列 , 配列 )配列要素を文字列により連結する
mb_substr()
mb_substr(部分文字列を取り出したい文字列,数値, 最大文字数、エンコーディング)文字列の一部を得る
explode
explode(‘区切る文字, 区切られる配列);explode — 文字列を文字列により分割する
implode()
implode ( ‘ ’ , 連結したい配列 )implode — 配列要素を文字列により連結する
str_replace()
str_replace(検索したい文字列 , 置き換える文字列文字 , 置換したい文字列 )str_replace — 検索文字列に一致したすべての文字列を置換する
strip_tags
strip_tags(HTML要素などを含んだ文字列);strip_tags — 文字列から HTML および PHP タグを取り除く
この関数は、指定した文字列 (str) から全ての NULL バイトと HTML および PHP タグを取り除きます。preg_split()
preg_split("//u", $string, -1, PREG_SPLIT_NO_EMPTY);preg_split — 正規表現で文字列を分割する
あとがき
PHP関数は多すぎて覚えれませんよね。
サービスで使用されているPHP関数のみまとめてくれていたら事前に予習でき楽だなと思い、記事作成に至りました。
これだけでは無いのでゆっくり追記していこうと思ってます!!ほぼ、下記参考を参考にしています。
https://www.php.net/manual/ja/function.str-replace.php
- 投稿日:2020-07-04T10:55:44+09:00
なんで自鯖のフォントファイルをサイトビルダーで使えないんじゃ^~
経緯
某Webサイトビルダーでサイトタイトルにフォントを使いたい
↓
カスタムコード機能でCSSを記述する@font-face { font-family: "custom-font"; src: url("https://my-rental-server.sample/font/tsukaitai.ttf"); } h1#kakkoii-title { font-family: custom-font, sans-selif; }↓
chrome先生「Access to font at 'https://my-rental-server.sample/font/tsukaitai.ttf' from origin 'https://suitbuilder.sample' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
」
↓
僕「ぴえん」HeaderでCORSの許可(よくわかってない)
ファイルのヘッダーでCORSの許可(?)を与えるといいらしい。
.htaccessがよくわかってない脆弱エンジニアな僕「ヘッダーを記述するならPHPだな?(名案」解決
フォントファイルのあるフォルダにこんなPHPを用意した。
readfont.php<?php header('Access-Control-Allow-Origin: *'); echo file_get_contents($_GET['a']); ?>そしてサイトビルダーのカスタムコードの
@font-face
はこんな感じ@font-face { font-family: "custom-font"; src: url("https://my-rental-server.sample/font/readfont?a=tsukaitai.ttf") format("truetype"); } /* 以下略 */結果
絶対に正解じゃないけど、解決したのでヨシ!