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 new file mode 100644 index 000000000..8e6068335 --- /dev/null +++ b/config/initializers/active_storage_previewers.rb @@ -0,0 +1,3 @@ +Rails.application.config.after_initialize do + Rails.application.config.active_storage.previewers.unshift HighResPopplerPdfPreviewer +end