From 5b951f012e04e6ef97e4ef645d53bdf433a9eb7f Mon Sep 17 00:00:00 2001 From: erdgeist Date: Tue, 21 Jul 2026 21:02:16 +0200 Subject: Implement model side of PDF raster preview generation --- app/models/concerns/file_attachment.rb | 24 ++++++++++++++++++------ lib/tasks/assets.rake | 6 ++++-- test/controllers/assets_controller_test.rb | 16 ++++++---------- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/app/models/concerns/file_attachment.rb b/app/models/concerns/file_attachment.rb index 548531f..6221312 100644 --- a/app/models/concerns/file_attachment.rb +++ b/app/models/concerns/file_attachment.rb @@ -31,6 +31,7 @@ module FileAttachment IMAGE_CONTENT_TYPES = %w[image/jpeg image/gif image/png image/webp].freeze VECTOR_CONTENT_TYPES = %w[image/svg+xml].freeze + RASTERIZED_CONTENT_TYPES = %w[application/pdf].freeze DISPLAYABLE_AS_IMAGE = IMAGE_CONTENT_TYPES + VECTOR_CONTENT_TYPES included do @@ -60,6 +61,11 @@ module FileAttachment has_variant?(:medium) end + def variant_filename(style) + return upload_file_name if style == :original || !RASTERIZED_CONTENT_TYPES.include?(upload_content_type) + File.basename(upload_file_name, ".*") + ".png" + end + private def build_upload_proxy @@ -89,11 +95,7 @@ module FileAttachment FileUtils.mkdir_p(File.dirname(original_path)) FileUtils.cp(uploaded_file.tempfile.path, original_path) - if IMAGE_CONTENT_TYPES.include?(upload_content_type) - generate_variants(original_path) - elsif VECTOR_CONTENT_TYPES.include?(upload_content_type) - generate_svg_variants(original_path) - end + generate_all_variants(original_path) end def generate_variants(original_path) @@ -112,6 +114,16 @@ module FileAttachment end end + def generate_all_variants(original_path) + if IMAGE_CONTENT_TYPES.include?(upload_content_type) + generate_variants(original_path) + elsif VECTOR_CONTENT_TYPES.include?(upload_content_type) + generate_svg_variants(original_path) + elsif RASTERIZED_CONTENT_TYPES.include?(upload_content_type) + generate_variants("#{original_path}[0]") + end + end + def delete_upload_files dir = upload_root.join(id.to_s) FileUtils.rm_rf(dir) if Dir.exist?(dir) @@ -135,7 +147,7 @@ module FileAttachment def url(style = :original) return "" if @record.upload_file_name.blank? - "/system/uploads/#{@record.id}/#{style}/#{@record.upload_file_name}" + "/system/uploads/#{@record.id}/#{style}/#{@record.variant_filename(style)}" end def content_type diff --git a/lib/tasks/assets.rake b/lib/tasks/assets.rake index 9d4b048..e778021 100644 --- a/lib/tasks/assets.rake +++ b/lib/tasks/assets.rake @@ -1,7 +1,9 @@ namespace :assets do desc "Regenerate ImageMagick variants for every image asset from its stored original -- rerun whenever a new style is added to FileAttachment::STYLES after assets already exist. Scope to one asset first with ASSET_ID=123." task :regenerate_variants => :environment do - scope = Asset.images + scope = Asset.where(upload_content_type: FileAttachment::IMAGE_CONTENT_TYPES + + FileAttachment::VECTOR_CONTENT_TYPES + + FileAttachment::RASTERIZED_CONTENT_TYPES) scope = scope.where(id: ENV["ASSET_ID"]) if ENV["ASSET_ID"].present? scope.find_each do |asset| @@ -12,7 +14,7 @@ namespace :assets do next end - asset.send(:generate_variants, original_path) + asset.send(:generate_all_variants, original_path) puts "Regenerated variants for Asset##{asset.id} (#{asset.name})" end end diff --git a/test/controllers/assets_controller_test.rb b/test/controllers/assets_controller_test.rb index 59ebab5..f834541 100644 --- a/test/controllers/assets_controller_test.rb +++ b/test/controllers/assets_controller_test.rb @@ -70,7 +70,7 @@ class AssetsControllerTest < ActionController::TestCase # --- create with PDF --- - test "create asset with PDF upload generates only original" do + test "create asset with PDF upload generates rasterized variants" do uploaded = Rack::Test::UploadedFile.new( Rails.root.join('test', 'fixtures', 'files', 'test_document.pdf'), 'application/pdf' @@ -81,18 +81,14 @@ class AssetsControllerTest < ActionController::TestCase assert_response :redirect asset = Asset.last - assert_equal 'test_document.pdf', asset.upload_file_name - assert_equal 'application/pdf', asset.upload_content_type - - # only original should exist, no image variants - original_path = Rails.root.join('public', 'system', 'uploads', - asset.id.to_s, 'original', 'test_document.pdf') + original_path = asset.send(:file_path, :original) assert File.exist?(original_path), "Expected original at #{original_path}" + assert_equal 'test_document.pdf', File.basename(original_path) %w[medium thumb headline large].each do |style| - path = Rails.root.join('public', 'system', 'uploads', - asset.id.to_s, style, 'test_document.pdf') - assert !File.exist?(path), "Expected no #{style} variant for PDF" + path = asset.send(:file_path, style) + assert File.exist?(path), "Expected a #{style} variant at #{path}" + assert_equal '.png', File.extname(path), "Expected #{style} variant to be a PNG, not a PDF" end end -- cgit v1.3