Feature #22481 » 0001-Render-PDF-thumbnail-using-ImageMagick-GhostScript.patch
app/controllers/admin_controller.rb | ||
---|---|---|
78 | 78 |
[:text_file_repository_writable, File.writable?(Attachment.storage_path)], |
79 | 79 |
["#{l :text_plugin_assets_writable} (./public/plugin_assets)", File.writable?(Redmine::Plugin.public_directory)], |
80 | 80 |
[:text_rmagick_available, Object.const_defined?(:Magick)], |
81 |
[:text_convert_available, Redmine::Thumbnail.convert_available?] |
|
81 |
[:text_convert_available, Redmine::Thumbnail.convert_available?], |
|
82 |
[:text_gs_available, Redmine::Thumbnail.gs_available?] |
|
82 | 83 |
] |
83 | 84 |
end |
84 | 85 |
end |
app/controllers/attachments_controller.rb | ||
---|---|---|
68 | 68 |
if stale?(:etag => tbnail) |
69 | 69 |
send_file tbnail, |
70 | 70 |
:filename => filename_for_content_disposition(@attachment.filename), |
71 |
:type => detect_content_type(@attachment), |
|
71 |
:type => detect_content_type(@attachment, true),
|
|
72 | 72 |
:disposition => 'inline' |
73 | 73 |
end |
74 | 74 |
else |
... | ... | |
184 | 184 |
@attachment.deletable? ? true : deny_access |
185 | 185 |
end |
186 | 186 | |
187 |
def detect_content_type(attachment) |
|
187 |
def detect_content_type(attachment, is_thumb = false)
|
|
188 | 188 |
content_type = attachment.content_type |
189 | 189 |
if content_type.blank? || content_type == "application/octet-stream" |
190 | 190 |
content_type = Redmine::MimeType.of(attachment.filename) |
191 | 191 |
end |
192 |
content_type.to_s |
|
192 |
content_type = content_type.to_s |
|
193 | ||
194 |
if is_thumb and content_type == "application/pdf" |
|
195 |
# PDF previews are stored in PNG format |
|
196 |
content_type = "image/png" |
|
197 |
end |
|
198 | ||
199 |
content_type |
|
193 | 200 |
end |
194 | 201 |
end |
app/models/attachment.rb | ||
---|---|---|
198 | 198 |
end |
199 | 199 | |
200 | 200 |
def thumbnailable? |
201 |
image? |
|
201 |
image? || (is_pdf? && Redmine::Thumbnail.gs_available?)
|
|
202 | 202 |
end |
203 | 203 | |
204 | 204 |
# Returns the full path the attachment thumbnail, or nil |
... | ... | |
218 | 218 |
target = File.join(self.class.thumbnails_storage_path, "#{id}_#{digest}_#{size}.thumb") |
219 | 219 | |
220 | 220 |
begin |
221 |
Redmine::Thumbnail.generate(self.diskfile, target, size) |
|
221 |
Redmine::Thumbnail.generate(self.diskfile, target, size, is_pdf?)
|
|
222 | 222 |
rescue => e |
223 | 223 |
logger.error "An error occured while generating thumbnail for #{disk_filename} to #{target}\nException was: #{e.message}" if logger |
224 | 224 |
return nil |
... | ... | |
245 | 245 |
self.filename =~ /\.(patch|diff)$/i |
246 | 246 |
end |
247 | 247 | |
248 |
def is_pdf? |
|
249 |
Redmine::MimeType.of(filename) == "application/pdf" |
|
250 |
end |
|
251 | ||
248 | 252 |
# Returns true if the file is readable |
249 | 253 |
def readable? |
250 | 254 |
File.readable?(diskfile) |
config/locales/de.yml | ||
---|---|---|
1061 | 1061 |
text_caracters_minimum: "Muss mindestens %{count} Zeichen lang sein." |
1062 | 1062 |
text_comma_separated: Mehrere Werte erlaubt (durch Komma getrennt). |
1063 | 1063 |
text_convert_available: ImageMagick-Konvertierung verfügbar (optional) |
1064 |
text_gs_available: ImageMagick PDF-Unterstützung verfügbar (optional) |
|
1064 | 1065 |
text_custom_field_possible_values_info: 'Eine Zeile pro Wert' |
1065 | 1066 |
text_default_administrator_account_changed: Administrator-Passwort geändert |
1066 | 1067 |
text_destroy_time_entries: Gebuchte Aufwände löschen |
config/locales/en-GB.yml | ||
---|---|---|
1097 | 1097 |
current password |
1098 | 1098 |
setting_mail_handler_excluded_filenames: Exclude attachments by name |
1099 | 1099 |
text_convert_available: ImageMagick convert available (optional) |
1100 |
text_gs_available: ImageMagick PDF support available (optional) |
|
1100 | 1101 |
label_link: Link |
1101 | 1102 |
label_only: only |
1102 | 1103 |
label_drop_down_list: drop-down list |
config/locales/en.yml | ||
---|---|---|
1101 | 1101 |
text_plugin_assets_writable: Plugin assets directory writable |
1102 | 1102 |
text_rmagick_available: RMagick available (optional) |
1103 | 1103 |
text_convert_available: ImageMagick convert available (optional) |
1104 |
text_gs_available: ImageMagick PDF support available (optional) |
|
1104 | 1105 |
text_destroy_time_entries_question: "%{hours} hours were reported on the issues you are about to delete. What do you want to do?" |
1105 | 1106 |
text_destroy_time_entries: Delete reported hours |
1106 | 1107 |
text_assign_time_entries_to_project: Assign reported hours to the project |
lib/redmine/thumbnail.rb | ||
---|---|---|
24 | 24 |
CONVERT_BIN = (Redmine::Configuration['imagemagick_convert_command'] || 'convert').freeze |
25 | 25 | |
26 | 26 |
# Generates a thumbnail for the source image to target |
27 |
def self.generate(source, target, size) |
|
27 |
def self.generate(source, target, size, is_pdf = false)
|
|
28 | 28 |
return nil unless convert_available? |
29 |
return nil if is_pdf && !gs_available? |
|
29 | 30 |
unless File.exists?(target) |
30 | 31 |
directory = File.dirname(target) |
31 | 32 |
unless File.exists?(directory) |
32 | 33 |
FileUtils.mkdir_p directory |
33 | 34 |
end |
34 | 35 |
size_option = "#{size}x#{size}>" |
35 |
cmd = "#{shell_quote CONVERT_BIN} #{shell_quote source} -thumbnail #{shell_quote size_option} #{shell_quote target}" |
|
36 | ||
37 |
if is_pdf |
|
38 |
cmd = "#{shell_quote CONVERT_BIN} #{shell_quote "#{source}[0]"} -thumbnail #{shell_quote size_option} #{shell_quote "png:#{target}"}" |
|
39 |
else |
|
40 |
cmd = "#{shell_quote CONVERT_BIN} #{shell_quote source} -thumbnail #{shell_quote size_option} #{shell_quote target}" |
|
41 |
end |
|
42 | ||
36 | 43 |
unless system(cmd) |
37 | 44 |
logger.error("Creating thumbnail failed (#{$?}):\nCommand: #{cmd}") |
38 | 45 |
return nil |
... | ... | |
48 | 55 |
@convert_available |
49 | 56 |
end |
50 | 57 | |
58 |
def self.gs_available? |
|
59 |
return @gs_available if defined?(@gs_available) |
|
60 | ||
61 |
@gs_available = system("gs -version") rescue false |
|
62 |
@gs_available ||= system("gswin32 -version") rescue false |
|
63 |
@gs_available ||= system("gswin64 -version") rescue false |
|
64 | ||
65 |
@gs_available |
|
66 |
end |
|
67 | ||
51 | 68 |
def self.logger |
52 | 69 |
Rails.logger |
53 | 70 |
end |