From ab602b301469f693ba153a01dd5b0973fd7acfd2 Mon Sep 17 00:00:00 2001 From: Justin Miller <16829344+jmilljr24@users.noreply.github.com> Date: Sat, 21 Mar 2026 13:00:31 -0400 Subject: [PATCH 1/2] use mupdf first for previews --- Dockerfile | 1 + config/initializers/active_storage_previewers.rb | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 config/initializers/active_storage_previewers.rb diff --git a/Dockerfile b/Dockerfile index f11923f7a..83471eb62 100644 --- a/Dockerfile +++ b/Dockerfile @@ -81,6 +81,7 @@ FROM base AS server RUN apt-get update -qq && apt-get install --no-install-recommends -y \ libvips \ poppler-utils \ + mupdf-tools \ tzdata \ libxml2 \ libxslt1.1 \ diff --git a/config/initializers/active_storage_previewers.rb b/config/initializers/active_storage_previewers.rb new file mode 100644 index 000000000..e3cb92ecf --- /dev/null +++ b/config/initializers/active_storage_previewers.rb @@ -0,0 +1,5 @@ +Rails.application.config.active_storage.previewers = [ + ActiveStorage::Previewer::MuPDFPreviewer, # move MuPDF to first for high-quality PDFs + ActiveStorage::Previewer::PopplerPDFPreviewer, + ActiveStorage::Previewer::VideoPreviewer +] From 30f53211fa46fe67cdb2be9bd03a6ae5437e3cd1 Mon Sep 17 00:00:00 2001 From: Justin Miller <16829344+jmilljr24@users.noreply.github.com> Date: Mon, 23 Mar 2026 09:52:53 -0400 Subject: [PATCH 2/2] use 300 dpi --- Dockerfile | 1 - .../high_res_poppler_pdf_previewer.rb | 38 +++++++++++++++++++ .../initializers/active_storage_previewers.rb | 8 ++-- 3 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 app/previewers/high_res_poppler_pdf_previewer.rb diff --git a/Dockerfile b/Dockerfile index 83471eb62..f11923f7a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -81,7 +81,6 @@ FROM base AS server RUN apt-get update -qq && apt-get install --no-install-recommends -y \ libvips \ poppler-utils \ - mupdf-tools \ tzdata \ libxml2 \ libxslt1.1 \ diff --git a/app/previewers/high_res_poppler_pdf_previewer.rb b/app/previewers/high_res_poppler_pdf_previewer.rb new file mode 100644 index 000000000..3880130bd --- /dev/null +++ b/app/previewers/high_res_poppler_pdf_previewer.rb @@ -0,0 +1,38 @@ +class HighResPopplerPdfPreviewer < ActiveStorage::Previewer + class << self + def accept?(blob) + blob.content_type == "application/pdf" && pdftoppm_exists? + end + + def pdftoppm_path + ActiveStorage.paths[:pdftoppm] || "pdftoppm" + end + + def pdftoppm_exists? + return @pdftoppm_exists if defined?(@pdftoppm_exists) + + @pdftoppm_exists = system(pdftoppm_path, "-v", out: File::NULL, err: File::NULL) + end + end + + def preview(**options) + download_blob_to_tempfile do |input| + draw_first_page_from input do |output| + yield io: output, filename: "#{blob.filename.base}.png", content_type: "image/png", **options + end + end + end + + private + + def draw_first_page_from(file, &block) + # High-DPI Poppler rendering + draw self.class.pdftoppm_path, + "-singlefile", + "-cropbox", + "-r", "300", + "-png", + file.path, + &block + end +end diff --git a/config/initializers/active_storage_previewers.rb b/config/initializers/active_storage_previewers.rb index e3cb92ecf..8e6068335 100644 --- a/config/initializers/active_storage_previewers.rb +++ b/config/initializers/active_storage_previewers.rb @@ -1,5 +1,3 @@ -Rails.application.config.active_storage.previewers = [ - ActiveStorage::Previewer::MuPDFPreviewer, # move MuPDF to first for high-quality PDFs - ActiveStorage::Previewer::PopplerPDFPreviewer, - ActiveStorage::Previewer::VideoPreviewer -] +Rails.application.config.after_initialize do + Rails.application.config.active_storage.previewers.unshift HighResPopplerPdfPreviewer +end