From 040cc3f25d618611afcccabbe29bbff949f80fdb Mon Sep 17 00:00:00 2001 From: miteruzo Date: Sat, 18 Jul 2026 12:15:32 +0900 Subject: [PATCH] #399 --- backend/app/controllers/preview_controller.rb | 14 +++++------ backend/app/models/post.rb | 2 -- .../app/services/preview/thumbnail_fetcher.rb | 12 +-------- .../src/pages/posts/PostImportReviewPage.tsx | 25 +++++++++++++++---- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/backend/app/controllers/preview_controller.rb b/backend/app/controllers/preview_controller.rb index 4829e2b..74fe1a9 100644 --- a/backend/app/controllers/preview_controller.rb +++ b/backend/app/controllers/preview_controller.rb @@ -18,14 +18,12 @@ class PreviewController < ApplicationController def thumbnail return render_bad_request('URL は必須です.') if params[:url].blank? - image = MiniMagick::Image.read(Preview::ThumbnailFetcher.fetch(params[:url])) - image.auto_orient - image.resize '180x180>' - image.format 'png' - width, height = image.dimensions - raise Preview::ThumbnailFetcher::GenerationFailed, 'サムネール画像の変換に失敗しました.' if width > 180 || height > 180 - - send_data image.to_blob, type: 'image/png', disposition: 'inline' + attachment = + Post.resized_thumbnail_attachment( + StringIO.new(Preview::ThumbnailFetcher.fetch(params[:url]))) + send_data attachment[:io].read, + type: attachment[:content_type], + disposition: 'inline' rescue Preview::UrlSafety::UnsafeUrl => e render_bad_request(e.message) rescue Preview::HttpFetcher::FetchTimeout => e diff --git a/backend/app/models/post.rb b/backend/app/models/post.rb index c8c209b..a2c63c9 100644 --- a/backend/app/models/post.rb +++ b/backend/app/models/post.rb @@ -17,8 +17,6 @@ class Post < ApplicationRecord MAX_SVG_DIMENSION = 4_096 MAX_SVG_PIXELS = 16_777_216 THUMBNAIL_PROCESS_TIMEOUT = 5.seconds - RASTER_THUMBNAIL_FORMATS = ['jpeg', 'png', 'gif', 'webp'].freeze - def self.resized_thumbnail_attachment(upload, content_type: nil) upload.rewind bytes = upload.read diff --git a/backend/app/services/preview/thumbnail_fetcher.rb b/backend/app/services/preview/thumbnail_fetcher.rb index efde3ab..f829fb7 100644 --- a/backend/app/services/preview/thumbnail_fetcher.rb +++ b/backend/app/services/preview/thumbnail_fetcher.rb @@ -4,10 +4,6 @@ module Preview RASTER_IMAGE_CONTENT_TYPES = [ 'image/jpeg', 'image/png', 'image/gif', 'image/webp' ].freeze - REMOTE_IMAGE_CONTENT_TYPES = [ - *RASTER_IMAGE_CONTENT_TYPES, - 'image/svg+xml' - ].freeze HTML_MAX_BYTES = 1.megabyte NICONICO_XML_MAX_BYTES = 256.kilobytes @@ -100,13 +96,7 @@ module Preview nil end - def self.allowed_remote_image_content_type?(content_type) - mime_type = content_type.to_s.split(';', 2).first.downcase.strip - REMOTE_IMAGE_CONTENT_TYPES.include?(mime_type) - end - private_class_method :fetch_image_or_nil, :fetch_image!, - :niconico_thumbnail_url, - :allowed_remote_image_content_type? + :niconico_thumbnail_url end end diff --git a/frontend/src/pages/posts/PostImportReviewPage.tsx b/frontend/src/pages/posts/PostImportReviewPage.tsx index 5b39eac..eea5bd1 100644 --- a/frontend/src/pages/posts/PostImportReviewPage.tsx +++ b/frontend/src/pages/posts/PostImportReviewPage.tsx @@ -110,6 +110,7 @@ const isRepairRow = (row: PostImportRow): boolean => && hasErrorMessages (row.validationErrors))) const DUPLICATE_URL_MESSAGE = 'URL が重複しています.' +const BULK_PROCESSING_FAILED_MESSAGE = '登録中にエラーが発生しました.' const rowMetadataPending = (row: PostImportRow): boolean => row.status === 'pending' @@ -314,14 +315,28 @@ const indexedBulkResults = ( } if (result?.status === 'skipped') { + const existingPostId = + result.existingPostId + ?? result.existingPost?.id + ?? row.existingPostId + if (existingPostId == null) + { + return { + sourceRow: row.sourceRow, + status: 'failed', + fieldWarnings: result.fieldWarnings, + baseWarnings: result.baseWarnings, + errors: { + ...(errors ?? { }), + base: [...new Set ([...(errors?.base ?? []), + BULK_PROCESSING_FAILED_MESSAGE])], + }, + recoverable: false } + } return { sourceRow: row.sourceRow, status: 'skipped', - existingPostId: - result.existingPostId - ?? result.existingPost?.id - ?? row.existingPostId - ?? row.sourceRow, + existingPostId, existingPost: result.existingPost, fieldWarnings: result.fieldWarnings, baseWarnings: result.baseWarnings,