From c3dc6180fb933b6498c60ca810867ecff4b882bf Mon Sep 17 00:00:00 2001 From: MAEDA Go Date: Thu, 20 Aug 2026 20:12:12 +0900 Subject: [PATCH 2/3] Preview Adobe Illustrator files saved in the PDF compatible format --- app/controllers/attachments_controller.rb | 6 ++++ app/models/attachment.rb | 5 ++- .../functional/attachments_controller_test.rb | 35 +++++++++++++++++++ test/unit/attachment_test.rb | 16 +++++---- 4 files changed, 55 insertions(+), 7 deletions(-) diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb index 168b344ed..699ba6670 100644 --- a/app/controllers/attachments_controller.rb +++ b/app/controllers/attachments_controller.rb @@ -296,6 +296,12 @@ class AttachmentsController < ApplicationController def detect_content_type(attachment, is_thumb = false) content_type = Redmine::MimeType.infer_type(attachment.content_type, attachment.filename) + if Marcel::Magic.child?(content_type, "application/pdf") + # Send PDF compatible files, such as Illustrator files, as PDF so that + # browsers display them inline + content_type = "application/pdf" + end + if is_thumb && !content_type.start_with?("image/") # Thumbnails of non-image files are stored in PNG format content_type = "image/png" diff --git a/app/models/attachment.rb b/app/models/attachment.rb index 6ac97daf3..7c3825e8f 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -322,8 +322,11 @@ class Attachment < ApplicationRecord /\.(patch|diff)$/i.match?(filename) end + # Returns true for PDF files, including PDF compatible files such as Adobe + # Illustrator (application/illustrator) def is_pdf? - Redmine::MimeType.of(filename) == "application/pdf" + type = Redmine::MimeType.infer_type(content_type, filename) + !!Marcel::Magic.child?(type, 'application/pdf') end def is_video? diff --git a/test/functional/attachments_controller_test.rb b/test/functional/attachments_controller_test.rb index f2eefcb4a..4050dcaa9 100644 --- a/test/functional/attachments_controller_test.rb +++ b/test/functional/attachments_controller_test.rb @@ -406,6 +406,41 @@ class AttachmentsControllerTest < Redmine::ControllerTest assert_match %r{\Aattachment}, @response.headers['Content-Disposition'] end + def test_show_pdf_compatible_illustrator_file_should_be_previewed + set_tmp_attachments_directory + attachment = Attachment.create!( + :file => mock_file_with_options( + :original_filename => 'logo.ai', + :content => File.binread("#{Rails.root}/test/fixtures/files/hello.pdf") + ), + :author_id => 2, + :container => Issue.find(1) + ) + assert_equal 'application/illustrator', attachment.content_type + + get(:show, :params => {:id => attachment.id}) + assert_response :success + assert_select 'div.filecontent.pdf object[type=?]', 'application/pdf' + end + + def test_download_pdf_compatible_illustrator_file_should_be_sent_inline_as_pdf + set_tmp_attachments_directory + attachment = Attachment.create!( + :file => mock_file_with_options( + :original_filename => 'logo.ai', + :content => File.binread("#{Rails.root}/test/fixtures/files/hello.pdf") + ), + :author_id => 2, + :container => Issue.find(1) + ) + + get(:download, :params => {:id => attachment.id}) + assert_response :success + # Sent as PDF so that browsers display it inline + assert_equal 'application/pdf', @response.media_type + assert_match %r{\Ainline}, @response.headers['Content-Disposition'] + end + def test_download_version_file_with_issue_tracking_disabled Project.find(1).disable_module! :issue_tracking get(:download, :params => {:id => 9}) diff --git a/test/unit/attachment_test.rb b/test/unit/attachment_test.rb index 820feafde..16a81d976 100644 --- a/test/unit/attachment_test.rb +++ b/test/unit/attachment_test.rb @@ -829,13 +829,17 @@ class AttachmentTest < ActiveSupport::TestCase def test_is_pdf to_test = { - 'report.pdf' => true, - # Illustrator files are not PDF files, even though some of them are - # PDF compatible - 'logo.ai' => false, + ['application/pdf', 'report.pdf'] => true, + # PDF compatible Illustrator files are detected as application/illustrator + ['application/illustrator', 'logo.ai'] => true, + # Illustrator files saved in the PostScript format are not PDF files + ['application/postscript', 'logo.ai'] => false, + # Attachments whose content type is undetermined fall back to the filename + ['application/octet-stream', 'report.pdf'] => true, } - to_test.each do |filename, expected| - assert_equal expected, Attachment.new(:filename => filename).is_pdf?, filename + to_test.each do |(content_type, filename), expected| + attachment = Attachment.new(:content_type => content_type, :filename => filename) + assert_equal expected, attachment.is_pdf?, "#{content_type} (#{filename})" end end end -- 2.55.0