【ITニュース解説】Printing receipts silently from a web app: what actually works in 2026
2026年10月09日に「Dev.to」が公開したITニュース「Printing receipts silently from a web app: what actually works in 2026」について初心者にもわかりやすく解説しています。
ITニュース概要
Webアプリからレシートをダイアログなしで印刷するには、ブラウザの制約からローカルPC上のエージェントを介すのが主流だ。CORSやセキュリティ対策、プリンターの実際の印刷幅への対応が重要。特に幅については、レシートを画像としてレンダリングしESC/POS形式で送る方法が、機種ごとの違いを吸収し確実に印刷できる。
ITニュース解説
Webアプリケーションからレシートプリンターへサイレント、つまりユーザーに印刷ダイアログを表示させずに直接印刷する機能は、POSシステムや飲食店、倉庫管理アプリなどで非常に重要だが、その実現は技術的に複雑な課題を伴う。この記事では、この課題を解決するための主要な方法とその注意点について解説する。
まず、最も手軽に試せるのが、Webブラウザに組み込まれているwindow.print()機能の利用だ。これはほぼすべてのブラウザで動作するが、必ず印刷ダイアログが表示されるため、レジ作業の効率を損ねる。また、ブラウザが勝手にページのマージンや拡大縮小を適用するため、レシートのような厳密なレイアウトを維持するのが難しい。さらに、紙の自動カットやキャッシュドロワーの開閉といったプリンター固有の機能は制御できないため、本格的な業務用システムには不向きだ。
次に、新しいWeb技術としてWebUSBやWeb SerialといったAPIを利用する方法がある。これらはWebブラウザがUSBやシリアルポートに接続されたデバイスと直接通信できるようにする技術で、追加のソフトウェアインストールが不要というメリットがある。しかし、現時点ではGoogle ChromeなどChromium系のブラウザでしか動作せず、デバイスと接続する際にはユーザーが手動で承認操作を行う必要がある。また、Windows環境では、既にインストールされているプリンタードライバーとWebUSB/Web SerialがUSBインターフェースの利用を競合する可能性があり、導入に際して課題となる場合がある。そのため、完全に管理されたキオスク端末など、特定の限定された環境での利用には適しているが、一般的なPOSシステムでの利用は難しいのが現状だ。
これらの課題を解決し、多くのPOSアプリケーションが最終的に採用しているのが「ローカルエージェント」というアプローチだ。これは、店舗のPC上に小型のプログラム(ローカルエージェント)をインストールし、Webアプリケーションはこのローカルエージェントに対してネットワーク経由で印刷指示を送り、ローカルエージェントがプリンターを制御する方法である。Webアプリケーションは、PC自身のIPアドレスである127.0.0.1(localhost)で動作するローカルエージェントにJavaScriptのfetch()関数などでリクエストを送信する。この方法にはいくつかの重要な注意点がある。
一つ目は、Chromeブラウザにおけるローカルネットワークアクセスに関するセキュリティルールだ。Webアプリケーションがhttps://でセキュアな接続をしている場合、http://127.0.0.1で動作するローカルエージェントを呼び出す際には、ブラウザがCORS(クロスオリジンリソース共有)のプリフライトリクエストという事前確認を行う。この際、ローカルエージェントからの応答にはAccess-Control-Allow-Private-Network: trueというヘッダーを含める必要がある。また、fetch()関数でtargetAddressSpaceオプションを指定する際には、'loopback'という値を正しく設定しないと、ループバックアドレスへのアクセスであっても通信が失敗する可能性があるため、注意が必要だ。
二つ目は、セキュリティの確保だ。ローカルエージェントはPC上で常時動作し、特定のポートでリクエストを待ち受けているため、悪意のあるウェブサイトから不正に利用されるリスクがある。これを防ぐためには、まずローカルエージェントを127.0.0.1アドレスにのみバインドし、外部からのアクセスを許可しないようにする。次に、Webブラウザからのリクエストに含まれるOrigin(オリジン)ヘッダーの値を検証し、許可されたWebアプリケーションからのリクエストのみを受け付けるようにする。Originヘッダーはブラウザが自動で設定し、Webページから偽装することはできないため、信頼性の高いチェックが可能だ。さらに、Hostヘッダーも検証し、DNSリバインディング攻撃を防ぐ対策も重要である。ブラウザ以外のアプリケーションからの呼び出しも許可する場合は、APIキーによる認証も導入すべきだ。
三つ目は、レシートプリンターの印字幅に関する実用上の問題だ。プリンターの仕様書に「80mm幅」とあっても、実際に印刷できるドット数(ピクセル数)はメーカーやモデルによって異なり、さらにプリンター内部のマージン設定によって利用可能な幅が変動することが一般的だ。この誤差により、文字が途切れたり、意図せず改行されたりする問題が発生しやすい。この問題を解決する最も確実な方法は、レシートの内容を固定された文字数でレイアウトするのではなく、レシート全体をビットマップ画像として生成し、その画像をプリンターに送信することだ。これにより、実際のフォント、正確なカラム配置、QRコード、バーコードなども含め、どのプリンターでも全く同じ見た目のレシートを印刷できるようになる。正確な印字幅を測定するには、幅いっぱいに定規のような画像を印刷し、実際に読み取れる範囲を確認するという手法が有効だ。
レシートプリンターを制御するためには、ESC/POSというコマンドセットが業界標準として広く利用されている。これは、プリンターの初期化、紙の部分カット、キャッシュドロワーの開口、テキストや画像の印刷といった様々な操作を、特定のバイト列(コマンド)を送信することで実行する。画像を印刷する際は「ラスタ画像」として送信するコマンドを利用するが、安価なプリンターでは一度に大きな画像を送信するとバッファが溢れることがあるため、画像を約128行程度の小さな帯(バンド)に分割して順次送信するのが推奨される。
ローカルエージェントがプリンターと通信する具体的な方法としては、OSの印刷スプーラーを経由する方法と、ネットワークプリンターに直接TCP/IPで接続する方法がある。Windows環境では、印刷ジョブを「RAW」(生データ)タイプとしてスプーラーに送り込むことで、OSのプリンタードライバーがデータを再レンダリングすることなく、ローカルエージェントが生成したバイト列をそのままプリンターに送ることができる。macOSやLinux環境では、CUPS(Common Unix Printing System)を通じてlp -o rawコマンドを実行することで、同様にRAW印刷が可能だ。また、多くのネットワーク対応レシートプリンターは、標準的にTCPポート9100でRAWバイト列を受け付けるため、このポートに直接データを送信することで印刷を実現できる。
これらの複雑な技術的課題を自身で実装することが難しい場合、既存のソリューションを利用することも選択肢となる。この記事の筆者も、これらの機能をすべて実装しパッケージ化した「Thermalink」というソリューションを提供している。これはWindows、macOS、Linuxに対応するローカルエージェントとJavaScript SDKから構成され、画像の印刷モード、印字幅を測定するキャリブレーション機能、QRコード、バーコード、ロゴの印刷、キャッシュドロワーの制御など、レシート印刷に必要な機能を一通り提供している。これにより、開発者は詳細なプリンター制御ロジックを自ら実装することなく、簡単にレシート印刷機能をWebアプリケーションに組み込める。ただし、このようなソリューションを使わずとも、ここで紹介した知識と技術があれば、自身でサイレント印刷システムを構築することは可能である。