NGW TECH BLOG
← 記事一覧へ
·#099

閉域網でOfficeの中身を見る結局作ったのはビューワーではなく、PDFへの配管だった

Office Onlineが使えない閉域網で、添付のWord・Excel・PowerPointをダウンロード無しで見られるようにした。作ったのは描画器ではなく「LibreOfficeでPDF化→pdf.jsで表示」の配管。ハマりどころは全部サーバ側の権限と環境変数だった。

MS Officeの簡易ビューワーを「自作」した。先に断っておく。描画エンジンは作っていない。 作ったのは、既存の部品をつなぐ配管だ。

なぜ要ったのか

Office Onlineは、閉域網(LGWAN)では使えない。外部のクラウドに文書を出せないからだ。ブラウザ向けの無償ビューワーも、Microsoftはやめて久しい。

運用の基本は「PDFを添付する」。でも現場には、WordやExcelをそのまま添付する人がいる。すると、中身を見るためだけにダウンロード → 起動 → 閉じるになる。決裁や収受の画面で毎回これは重い。

そこで、見るだけの簡易ビューワーを内蔵した。

配管の中身

  1. 添付タブの「簡易表示する」を押す
  2. サーバで LibreOffice(headless)がPDFへ変換する
  3. 既存の 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 loadedApache配下のPHPには LANG が無い。sofficeに LC_ALL=C.UTF-8 を明示して渡す
4:変換先のディレクトリが作れないmkdir(): Operation not permittedApache配下では、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をつなぐだけで足りた。作る量を減らすほど、後で直す場所が減る。