PDFをWebブラウザで閲覧できる簡易的なビュアーを作成してみました。
ファイル管理アプリの登録等をせずにネットワーク内で複数ユーザーが閲覧できます。
当然の事ながら、ファイル管理アプリの方が便利ではありますが
小規模企業等、社内ルール等でアプリの使用が難しかったり、
書き換え次第で機能の広がりも期待できる事やシンプルさと表示の速さでもPHPが妥当と判断しました。
その他諸々の理由から時代に逆光した構成ですが、現場レベルで使用する上では充分なものです。
編集機能などはNASの機能次第のようなので、勉強&運用しながら試行錯誤。
表示までは進んだので、ここまでをメモとして残します。
管理者のPC上でPHPがインストールされていることが前提です。
(インストールされていない場合は、PHPのインストールから行う)
最近のMacは標準では入っていないみたい。
(例)フォルダ構成
共有ネットワーク内に設置

**閲覧用(iframeでPDFを開く)**
index.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>PDF一覧</title>
<style>
body { font-family: sans-serif; margin: 0; display: flex; height: 100vh; }
#menu { width: 300px; background: #f7f7f7; overflow-y: auto; border-right: 1px solid #ccc; padding: 10px; }
#viewer { flex-grow: 1; }
iframe { width: 100%; height: 100%; border: none; }
ul { list-style-type: none; padding-left: 20px; margin: 0; }
li { cursor: default; }
.folder > span::before { content: "📁 "; cursor: pointer; }
.file::before { content: "📄 "; }
.children { display: none; }
</style>
<script>
function toggleFolder(el) {
const children = el.parentElement.querySelector('.children');
if (children) {
children.style.display = children.style.display === 'none' ? 'block' : 'none';
}
}
</script>
</head>
<body>
<div id="menu">
<h3>PDF一覧</h3>
<?php
function listFiles($dir, $relPath = '') {
$items = array_diff(scandir($dir), ['.', '..', '.DS_Store']);
if (empty($items)) return '';
$html = '<ul>';
foreach ($items as $item) {
$fullPath = $dir . '/' . $item;
$displayPath = $relPath . $item;
if (is_dir($fullPath)) {
$html .= '<li class="folder"><span onclick="toggleFolder(this)">' . htmlspecialchars($item) . '</span>';
$html .= '<div class="children">' . listFiles($fullPath, $relPath . $item . '/') . '</div>';
$html .= '</li>';
} else {
$ext = strtolower(pathinfo($item, PATHINFO_EXTENSION));
if ($ext === 'pdf') {
$html .= '<li class="file"><a href="pdfs/' . htmlspecialchars($displayPath) . '" target="viewer">' . htmlspecialchars($item) . '</a></li>';
} else {
$html .= '<li class="file"><a href="pdfs/' . htmlspecialchars($displayPath) . '" download>' . htmlspecialchars($item) . '</a></li>';
}
}
}
$html .= '</ul>';
return $html;
}
$pdfDir = __DIR__ . '/pdfs';
if (is_dir($pdfDir)) {
echo listFiles($pdfDir);
} else {
echo "<p>PDFフォルダが見つかりません。</p>";
}
?>
</div>
<div id="viewer">
<iframe name="viewer"></iframe>
</div>
</body>
</html>
**PHP起動のために作成したファイル**
【本体】 start_php_server.sh
ネットワークにマウントされているかの確認と、指定ポートのクリーンアップ(kill)を行う
【sh起動用の入口】 php_server_launcher.app
shを起動させるショートカット・実行ボタン(デスクトップに配置)
【閲覧用】index.php
閲覧用のPDFフォルダと同じ共有内に格納
**ワークフロー**
共有ネットワークをショートカットでマウントし
↓
作成したランチャー
php_server_launcher.appを開き
↓
作成したスクリプトが起動して
start_php_server.sh
↓
PHPの仮想サーバとなる
↓
共有ネットワーク上の指定フォルダ内のindex.phpが表示、PDFが閲覧可能になる
もう少しスマートな方法は無いかしら・・・
**コードの解説**
社内ネットワーク内で運用する場合なので、閲覧するPDFファイルは、共有内の指定フォルダに格納。
今回の場合は管理者PCから共有ネットワークフォルダにマウント+PHPを走らせる必要があるため、
空いてるポートを探してPHPを自動起動させるshファイルと起動用のランチャー(ショートカット)を作成。
PC起動時に自動実行させることも可能ですが、運用上の理由から、現状では手動起動の方式を採用しています。
start_php_server.shを作成(管理者のホームフォルダに保存 /Users/◯◯◯/ )
#!/bin/bash
PHP_BIN="/usr/local/bin/php"
DOCROOT="/ディレクトリのアドレス/viewer"
PORT=ポート番号
# 共有ネットワークがマウントされていなければ終了
if [ ! -d "$DOCROOT" ]; then
echo "共有ネットワークがマウントされていません"
exit 1
fi
# 0000–0000(ポート番号)を使用しているプロセスをすべて kill
for p in {0000..0000}; do
PID=$(lsof -ti tcp:$p)
if [ -n "$PID" ]; then
kill -9 $PID
fi
done
# PHP サーバ起動(バックグラウンド)
"$PHP_BIN" -S localhost:$PORT -t "$DOCROOT" >/tmp/php_server.log 2>&1 &
●ターミナルで実行権限を追加
chmod +x ~/start_php_server.sh
続けて動作テスト
~/start_php_server.sh
エラーが無ければOK
php_server_launcher.appを作成
Users/◯◯◯/start_php_server.sh
確認
lsof -i :ポート番号を入れる
php_server_launcher.appをクリックすることで本体shが起動する
歯車が回っていれば成功。
ブラウザでhttp://localhost:ポート番号を開く
index.phpが表示されリンクされいるフォルダ内のPDFも閲覧可能となる。