aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTerence Lee <hone02@gmail.com>2018-02-05 19:33:35 -0600
committerGeorge Claghorn <george@basecamp.com>2018-03-06 13:33:33 -0500
commit0b717c20458d12191f479fc693dd1ca1eb11c050 (patch)
tree6bcd9dd08f792a35235a96f392a79fd2ac0cdbc2
parent060ed201e444785135ce9a4baea069079257295e (diff)
downloadrails-0b717c20458d12191f479fc693dd1ca1eb11c050.tar.gz
rails-0b717c20458d12191f479fc693dd1ca1eb11c050.tar.bz2
rails-0b717c20458d12191f479fc693dd1ca1eb11c050.zip
Provide an alternative PDF previewer based on Poppler
mutool is licensed under the Affero GPL, which has strict distribution requirements. Poppler is licensed under the more liberal GPL, making it a good alternative for those who can't use mutool.
-rw-r--r--.travis.yml1
-rw-r--r--activestorage/app/models/active_storage/preview.rb7
-rw-r--r--activestorage/lib/active_storage/engine.rb5
-rw-r--r--activestorage/lib/active_storage/previewer/mupdf_previewer.rb36
-rw-r--r--activestorage/lib/active_storage/previewer/pdf_previewer.rb26
-rw-r--r--activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb35
-rw-r--r--activestorage/test/previewer/mupdf_previewer_test.rb (renamed from activestorage/test/previewer/pdf_previewer_test.rb)6
-rw-r--r--activestorage/test/previewer/poppler_pdf_previewer_test.rb23
8 files changed, 104 insertions, 35 deletions
diff --git a/.travis.yml b/.travis.yml
index 2513e87114..09e16698e4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -24,6 +24,7 @@ addons:
- ffmpeg
- mupdf
- mupdf-tools
+ - poppler-utils
bundler_args: --without test --jobs 3 --retry 3
before_install:
diff --git a/activestorage/app/models/active_storage/preview.rb b/activestorage/app/models/active_storage/preview.rb
index 45efd26214..2b87897183 100644
--- a/activestorage/app/models/active_storage/preview.rb
+++ b/activestorage/app/models/active_storage/preview.rb
@@ -21,10 +21,9 @@
#
# Outside of a Rails application, modify +ActiveStorage.previewers+ instead.
#
-# The built-in previewers rely on third-party system libraries:
-#
-# * {ffmpeg}[https://www.ffmpeg.org]
-# * {mupdf}[https://mupdf.com] (version 1.8 or newer)
+# The built-in previewers rely on third-party system libraries. Specifically, the built-in video previewer requires
+# {ffmpeg}[https://www.ffmpeg.org]. Two PDF previewers are provided: one requires {Poppler}[https://poppler.freedesktop.org],
+# and the other requires {mupdf}[https://mupdf.com] (version 1.8 or newer). To preview PDFs, install either Poppler or mupdf.
#
# These libraries are not provided by Rails. You must install them yourself to use the built-in previewers. Before you
# install and use third-party software, make sure you understand the licensing implications of doing so.
diff --git a/activestorage/lib/active_storage/engine.rb b/activestorage/lib/active_storage/engine.rb
index 1e223f9f17..1385e2aa84 100644
--- a/activestorage/lib/active_storage/engine.rb
+++ b/activestorage/lib/active_storage/engine.rb
@@ -3,7 +3,8 @@
require "rails"
require "active_storage"
-require "active_storage/previewer/pdf_previewer"
+require "active_storage/previewer/poppler_pdf_previewer"
+require "active_storage/previewer/mupdf_previewer"
require "active_storage/previewer/video_previewer"
require "active_storage/analyzer/image_analyzer"
@@ -14,7 +15,7 @@ module ActiveStorage
isolate_namespace ActiveStorage
config.active_storage = ActiveSupport::OrderedOptions.new
- config.active_storage.previewers = [ ActiveStorage::Previewer::PDFPreviewer, ActiveStorage::Previewer::VideoPreviewer ]
+ config.active_storage.previewers = [ ActiveStorage::Previewer::PopplerPDFPreviewer, ActiveStorage::Previewer::MuPDFPreviewer, ActiveStorage::Previewer::VideoPreviewer ]
config.active_storage.analyzers = [ ActiveStorage::Analyzer::ImageAnalyzer, ActiveStorage::Analyzer::VideoAnalyzer ]
config.active_storage.paths = ActiveSupport::OrderedOptions.new
diff --git a/activestorage/lib/active_storage/previewer/mupdf_previewer.rb b/activestorage/lib/active_storage/previewer/mupdf_previewer.rb
new file mode 100644
index 0000000000..ae02a4889d
--- /dev/null
+++ b/activestorage/lib/active_storage/previewer/mupdf_previewer.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module ActiveStorage
+ class Previewer::MuPDFPreviewer < Previewer
+ class << self
+ def accept?(blob)
+ blob.content_type == "application/pdf" && mutool_exists?
+ end
+
+ def mutool_path
+ ActiveStorage.paths[:mutool] || "mutool"
+ end
+
+ def mutool_exists?
+ return @mutool_exists unless @mutool_exists.nil?
+
+ system mutool_path, out: File::NULL, err: File::NULL
+
+ @mutool_exists = $?.exitstatus == 1
+ end
+ end
+
+ def preview
+ 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"
+ end
+ end
+ end
+
+ private
+ def draw_first_page_from(file, &block)
+ draw self.class.mutool_path, "draw", "-F", "png", "-o", "-", file.path, "1", &block
+ end
+ end
+end
diff --git a/activestorage/lib/active_storage/previewer/pdf_previewer.rb b/activestorage/lib/active_storage/previewer/pdf_previewer.rb
deleted file mode 100644
index 426ff51eb1..0000000000
--- a/activestorage/lib/active_storage/previewer/pdf_previewer.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module ActiveStorage
- class Previewer::PDFPreviewer < Previewer
- def self.accept?(blob)
- blob.content_type == "application/pdf"
- end
-
- def preview
- 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"
- end
- end
- end
-
- private
- def draw_first_page_from(file, &block)
- draw mutool_path, "draw", "-F", "png", "-o", "-", file.path, "1", &block
- end
-
- def mutool_path
- ActiveStorage.paths[:mutool] || "mutool"
- end
- end
-end
diff --git a/activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb b/activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb
new file mode 100644
index 0000000000..2a787362cf
--- /dev/null
+++ b/activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module ActiveStorage
+ class Previewer::PopplerPDFPreviewer < 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 unless @pdftoppm_exists.nil?
+
+ @pdftoppm_exists = system(pdftoppm_path, "-v", out: File::NULL, err: File::NULL)
+ end
+ end
+
+ def preview
+ 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"
+ end
+ end
+ end
+
+ private
+ def draw_first_page_from(file, &block)
+ # use 72 dpi to match thumbnail dimesions of the PDF
+ draw self.class.pdftoppm_path, "-singlefile", "-r", "72", "-png", file.path, &block
+ end
+ end
+end
diff --git a/activestorage/test/previewer/pdf_previewer_test.rb b/activestorage/test/previewer/mupdf_previewer_test.rb
index fe32f39be4..6c2db6fcbf 100644
--- a/activestorage/test/previewer/pdf_previewer_test.rb
+++ b/activestorage/test/previewer/mupdf_previewer_test.rb
@@ -3,15 +3,15 @@
require "test_helper"
require "database/setup"
-require "active_storage/previewer/pdf_previewer"
+require "active_storage/previewer/mupdf_previewer"
-class ActiveStorage::Previewer::PDFPreviewerTest < ActiveSupport::TestCase
+class ActiveStorage::Previewer::MuPDFPreviewerTest < ActiveSupport::TestCase
setup do
@blob = create_file_blob(filename: "report.pdf", content_type: "application/pdf")
end
test "previewing a PDF document" do
- ActiveStorage::Previewer::PDFPreviewer.new(@blob).preview do |attachable|
+ ActiveStorage::Previewer::MuPDFPreviewer.new(@blob).preview do |attachable|
assert_equal "image/png", attachable[:content_type]
assert_equal "report.png", attachable[:filename]
diff --git a/activestorage/test/previewer/poppler_pdf_previewer_test.rb b/activestorage/test/previewer/poppler_pdf_previewer_test.rb
new file mode 100644
index 0000000000..2b41c8b642
--- /dev/null
+++ b/activestorage/test/previewer/poppler_pdf_previewer_test.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require "test_helper"
+require "database/setup"
+
+require "active_storage/previewer/poppler_pdf_previewer"
+
+class ActiveStorage::Previewer::PopplerPDFPreviewerTest < ActiveSupport::TestCase
+ setup do
+ @blob = create_file_blob(filename: "report.pdf", content_type: "application/pdf")
+ end
+
+ test "previewing a PDF document" do
+ ActiveStorage::Previewer::PopplerPDFPreviewer.new(@blob).preview do |attachable|
+ assert_equal "image/png", attachable[:content_type]
+ assert_equal "report.png", attachable[:filename]
+
+ image = MiniMagick::Image.read(attachable[:io])
+ assert_equal 612, image.width
+ assert_equal 792, image.height
+ end
+ end
+end