閉域網でOfficeの中身を見る結局作ったのはビューワーではなく、PDFへの配管だった
Office Onlineが使えない閉域網で、添付のWord・Excel・PowerPointをダウンロード無しで見られるようにした。作ったのは描画器ではなく「LibreOfficeでPDF化→pdf.jsで表示」の配管。ハマりどころは全部サーバ側の権限と環境変数だった。
MS Officeの簡易ビューワーを「自作」した。先に断っておく。描画エンジンは作っていない。 作ったのは、既存の部品をつなぐ配管だ。
なぜ要ったのか
Office Onlineは、閉域網(LGWAN)では使えない。外部のクラウドに文書を出せないからだ。ブラウザ向けの無償ビューワーも、Microsoftはやめて久しい。
運用の基本は「PDFを添付する」。でも現場には、WordやExcelをそのまま添付する人がいる。すると、中身を見るためだけにダウンロード → 起動 → 閉じるになる。決裁や収受の画面で毎回これは重い。
そこで、見るだけの簡易ビューワーを内蔵した。
配管の中身
- 添付タブの「簡易表示する」を押す
- サーバで LibreOffice(headless)がPDFへ変換する
- 既存の pdf.js の経路で、そのまま画面に出す
押したときに、その1件だけ変換する。結果は原本の横にキャッシュし、原本が更新されたら作り直す。アップロード時の一括変換も、過去分のバッチも要らない。
失敗1:ブラウザ内のJSだけで描こうとして捨てた
最初に考えたのは、docx-previewやSheetJSのような、ブラウザ側のJSによる近似表示だ。サーバに何も入れずに済む。
試すと、罫線が崩れ、pptxはまともに出なかった。 「簡易」でも、役所の様式(罫線だらけのExcel)で崩れたら意味が無い。
サーバ側でLibreOfficeにPDF化させる方式へ転換した。見た目の忠実度は「PDFとして正しいか」で保証できる。しかも既にあるpdf.jsの経路に乗せたので、新しい表示コードはほぼ要らなかった。
失敗2〜5:動かなかった理由は、全部サーバ環境だった
| 失敗 | 症状 | 原因と対処 |
|---|---|---|
| 2:コマンドラインでは動くのに、画面から動かない | /proc not mounted で soffice が落ちる | Ubuntuの apache2.service は ProcSubset=pid。drop-inで ProcSubset=all に戻した(MemoryDenyWriteExecute は無関係だった) |
| 3:日本語のファイル名だけ開けない | source file could not be loaded | Apache配下のPHPには LANG が無い。sofficeに LC_ALL=C.UTF-8 を明示して渡す |
| 4:変換先のディレクトリが作れない | mkdir(): Operation not permitted | Apache配下では、modeにsetgid(02775)を付けるとEPERM(RestrictSUIDSGID)。0775にする |
| 5:snap版のLibreOfficeが呼べない | www-dataから起動できない | snapは隔離される。apt版(deb) を入れる |
共通点は1つ。コマンドラインで動いても、Apache配下(www-data+systemdの制限)では動かない。 手元で成功した時点で安心すると、ここで2日使う。
もう1つ。同時に2本動かすと、2本目が1本目に処理を渡して、何もせず終わることがある(同じプロファイルを使うため)。機体全体で flock をかけて、1本ずつに直列化した。待っている間に他の人が同じPDFを作っていれば、それを使う。
置き場所と配信
変換結果を files/ の中に置くと、共有ファイルの走査やアップローダが「未登録ファイル」として拾ってしまう。だから、原本の横の officePreview/ に置いた。
- 原本と同じディスクなので、決裁や収受を消すと一緒に消える。孤児が残らない。
- バックアップも原本と一緒に取れる。
- 配信側のApacheは、
officePreview/をPDF以外403。Cache-Control: no-cacheで、同じURLでも毎回確かめさせる。
「簡易」と言い切る割り切り
- フォント。 MS明朝・MSゴシックはライセンス品なので、イメージに入れない。fontconfigの置換でIPAex明朝・ゴシックなどに寄せる。その結果、行末や改ページは原本とずれる。 画面には「簡易表示です。正式にはダウンロードしてください」と注記を添えた。
- 変換は1件数秒かかり、PHPの同時実行枠を塞ぐ。だから「押されたときだけ、一度だけ」。
- LibreOfficeが無い機体(Mac版MAMPなど)では既定オフ(定数
OFFICE_PREVIEW=0)。1にしても、sofficeが無ければ従来どおり、ダウンロードのみに倒れる。「押しても出ない」を作らない。 - 対象は、添付の
files/直下だけ。それ以外は「この場所は変換できません」と出す。
AIとの協働作業での学び
AIは、近似で済ませる案から出してくる。 最初のJS案は、サーバに何も要らず、速くて、きれいな提案だった。でも役所の様式で試すと崩れる。実際の文書を通すまで、案の良し悪しは分からない。
「動いた」は、どの環境で動いたかを聞く。 失敗2〜5は、AIが書いたコードの誤りではなく、実行環境の差だった。AIは手元のシェルで成功させて「完了」と言う。Apache配下で動いたかどうかは、こちらが確かめる。
「作らない」のも設計だった。 描画器を自作する案も、AIは出せたと思う。でも、LibreOfficeとpdf.jsをつなぐだけで足りた。作る量を減らすほど、後で直す場所が減る。