summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGo MAEDA <maeda@farend.jp>2019-05-12 03:55:56 +0000
committerGo MAEDA <maeda@farend.jp>2019-05-12 03:55:56 +0000
commitc4a4133178b83c2c115df1947302c785b2885467 (patch)
tree10aeb523e06a613a9b8942b67cae947a23b2b4e9
parenta5b9632772294981b5c96fb5f8273a386d84f90c (diff)
downloadredmine-c4a4133178b83c2c115df1947302c785b2885467.tar.gz
redmine-c4a4133178b83c2c115df1947302c785b2885467.zip
Render PDF thumbnail using ImageMagick/GhostScript (#22481).
Patch by Gregor Schmidt. git-svn-id: http://svn.redmine.org/redmine/trunk@18158 e93f8b46-1217-0410-a6f0-8f06a7374b81
-rw-r--r--app/controllers/admin_controller.rb3
-rw-r--r--app/controllers/attachments_controller.rb16
-rw-r--r--app/models/attachment.rb4
-rw-r--r--config/locales/de.yml1
-rw-r--r--config/locales/en-GB.yml1
-rw-r--r--config/locales/en.yml1
-rw-r--r--lib/redmine/thumbnail.rb33
7 files changed, 49 insertions, 10 deletions
diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb
index 91d3b0712..eb2288eff 100644
--- a/app/controllers/admin_controller.rb
+++ b/app/controllers/admin_controller.rb
@@ -77,7 +77,8 @@ class AdminController < ApplicationController
[:text_file_repository_writable, File.writable?(Attachment.storage_path)],
["#{l :text_plugin_assets_writable} (./public/plugin_assets)", File.writable?(Redmine::Plugin.public_directory)],
[:text_rmagick_available, Object.const_defined?(:Magick)],
- [:text_convert_available, Redmine::Thumbnail.convert_available?]
+ [:text_convert_available, Redmine::Thumbnail.convert_available?],
+ [:text_gs_available, Redmine::Thumbnail.gs_available?]
]
end
end
diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb
index bc558fdc0..4817149a4 100644
--- a/app/controllers/attachments_controller.rb
+++ b/app/controllers/attachments_controller.rb
@@ -83,7 +83,7 @@ class AttachmentsController < ApplicationController
if stale?(:etag => tbnail)
send_file tbnail,
:filename => filename_for_content_disposition(@attachment.filename),
- :type => detect_content_type(@attachment),
+ :type => detect_content_type(@attachment, true),
:disposition => 'inline'
end
else
@@ -236,12 +236,20 @@ class AttachmentsController < ApplicationController
@attachment.deletable? ? true : deny_access
end
- def detect_content_type(attachment)
+ def detect_content_type(attachment, is_thumb = false)
content_type = attachment.content_type
if content_type.blank? || content_type == "application/octet-stream"
- content_type = Redmine::MimeType.of(attachment.filename)
+ content_type =
+ Redmine::MimeType.of(attachment.filename).presence ||
+ "application/octet-stream"
end
- content_type.presence || "application/octet-stream"
+
+ if is_thumb && content_type == "application/pdf"
+ # PDF previews are stored in PNG format
+ content_type = "image/png"
+ end
+
+ content_type
end
def disposition(attachment)
diff --git a/app/models/attachment.rb b/app/models/attachment.rb
index 362ac1fde..a0d712a34 100644
--- a/app/models/attachment.rb
+++ b/app/models/attachment.rb
@@ -201,7 +201,7 @@ class Attachment < ActiveRecord::Base
end
def thumbnailable?
- image?
+ image? || (is_pdf? && Redmine::Thumbnail.gs_available?)
end
# Returns the full path the attachment thumbnail, or nil
@@ -221,7 +221,7 @@ class Attachment < ActiveRecord::Base
target = thumbnail_path(size)
begin
- Redmine::Thumbnail.generate(self.diskfile, target, size)
+ Redmine::Thumbnail.generate(self.diskfile, target, size, is_pdf?)
rescue => e
logger.error "An error occured while generating thumbnail for #{disk_filename} to #{target}\nException was: #{e.message}" if logger
return nil
diff --git a/config/locales/de.yml b/config/locales/de.yml
index c0dec9fbb..01a9701e3 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -1066,6 +1066,7 @@ de:
text_caracters_minimum: "Muss mindestens %{count} Zeichen lang sein."
text_comma_separated: Mehrere Werte erlaubt (durch Komma getrennt).
text_convert_available: ImageMagick-Konvertierung verfügbar (optional)
+ text_gs_available: ImageMagick PDF-Unterstützung verfügbar (optional)
text_custom_field_possible_values_info: 'Eine Zeile pro Wert'
text_default_administrator_account_changed: Administrator-Passwort geändert
text_destroy_time_entries: Gebuchte Aufwände löschen
diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml
index 8b744afbb..67a7f4b4b 100644
--- a/config/locales/en-GB.yml
+++ b/config/locales/en-GB.yml
@@ -1087,6 +1087,7 @@ en-GB:
current password
setting_mail_handler_excluded_filenames: Exclude attachments by name
text_convert_available: ImageMagick convert available (optional)
+ text_gs_available: ImageMagick PDF support available (optional)
label_link: Link
label_only: only
label_drop_down_list: drop-down list
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 17f9c7458..7b25de4a2 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1169,6 +1169,7 @@ en:
text_plugin_assets_writable: Plugin assets directory writable
text_rmagick_available: RMagick available (optional)
text_convert_available: ImageMagick convert available (optional)
+ text_gs_available: ImageMagick PDF support available (optional)
text_destroy_time_entries_question: "%{hours} hours were reported on the issues you are about to delete. What do you want to do?"
text_destroy_time_entries: Delete reported hours
text_assign_time_entries_to_project: Assign reported hours to the project
diff --git a/lib/redmine/thumbnail.rb b/lib/redmine/thumbnail.rb
index 31ac62272..278717273 100644
--- a/lib/redmine/thumbnail.rb
+++ b/lib/redmine/thumbnail.rb
@@ -25,12 +25,18 @@ module Redmine
extend Redmine::Utils::Shell
CONVERT_BIN = (Redmine::Configuration['imagemagick_convert_command'] || 'convert').freeze
- ALLOWED_TYPES = %w(image/bmp image/gif image/jpeg image/png)
+ ALLOWED_TYPES = %w(image/bmp image/gif image/jpeg image/png application/pdf)
# Generates a thumbnail for the source image to target
- def self.generate(source, target, size)
+ def self.generate(source, target, size, is_pdf = false)
return nil unless convert_available?
+ return nil if is_pdf && !gs_available?
unless File.exists?(target)
+ mime_type = File.open(source) {|f| MimeMagic.by_magic(f).try(:type) }
+ return nil if mime_type.nil?
+ return nil if !ALLOWED_TYPES.include? mime_type
+ return nil if is_pdf && mime_type != "application/pdf"
+
# Make sure we only invoke Imagemagick if the file type is allowed
unless File.open(source) {|f| ALLOWED_TYPES.include? MimeMagic.by_magic(f).try(:type) }
return nil
@@ -40,7 +46,12 @@ module Redmine
FileUtils.mkdir_p directory
end
size_option = "#{size}x#{size}>"
- cmd = "#{shell_quote CONVERT_BIN} #{shell_quote source} -auto-orient -thumbnail #{shell_quote size_option} #{shell_quote target}"
+
+ if is_pdf
+ cmd = "#{shell_quote CONVERT_BIN} #{shell_quote "#{source}[0]"} -thumbnail #{shell_quote size_option} #{shell_quote "png:#{target}"}"
+ else
+ cmd = "#{shell_quote CONVERT_BIN} #{shell_quote source} -auto-orient -thumbnail #{shell_quote size_option} #{shell_quote target}"
+ end
unless system(cmd)
logger.error("Creating thumbnail failed (#{$?}):\nCommand: #{cmd}")
return nil
@@ -61,6 +72,22 @@ module Redmine
@convert_available
end
+ def self.gs_available?
+ return @gs_available if defined?(@gs_available)
+
+ if Redmine::Platform.mswin?
+ @gs_available = false
+ else
+ begin
+ `gs -version`
+ @gs_available = $?.success?
+ rescue
+ @gs_available = false
+ end
+ end
+ @gs_available
+ end
+
def self.logger
Rails.logger
end