mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-12-26 01:35:34 +08:00
Merge pull request #1798 from biosistemika/jg_sci_3145_thumbnail_preview
File preview on new attachments layout [SCI-3145]
This commit is contained in:
commit
bbfe2b9c89
13 changed files with 130 additions and 53 deletions
|
@ -1,8 +1,16 @@
|
|||
FROM ruby:2.5.5
|
||||
MAINTAINER BioSistemika <info@biosistemika.com>
|
||||
|
||||
# Get version of Debian (lsb_release substitute) and save it to /tmp/lsb_release for further commands
|
||||
RUN cat /etc/os-release | grep -Po "VERSION=.*\(\K\w+" | tee /tmp/lsb_release
|
||||
|
||||
# Add Debian stretch backports repository
|
||||
RUN echo "deb http://http.debian.net/debian $(cat /tmp/lsb_release)-backports main" \
|
||||
| tee /etc/apt/sources.list.d/$(cat /tmp/lsb_release)-backports.list
|
||||
|
||||
# additional dependecies
|
||||
# libSSL-1.0 is required by wkhtmltopdf binary
|
||||
# libreoffice for file preview generation
|
||||
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - && \
|
||||
apt-get update -qq && \
|
||||
apt-get install -y \
|
||||
|
@ -14,6 +22,7 @@ RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - && \
|
|||
unison \
|
||||
sudo graphviz --no-install-recommends \
|
||||
libfile-mimeinfo-perl && \
|
||||
apt-get install -y --no-install-recommends -t $(cat /tmp/lsb_release)-backports libreoffice && \
|
||||
npm install -g yarn && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
FROM ruby:2.5.5
|
||||
MAINTAINER BioSistemika <info@biosistemika.com>
|
||||
|
||||
RUN echo deb "http://http.debian.net/debian stretch-backports main" >> /etc/apt/sources.list
|
||||
|
||||
# additional dependecies
|
||||
# libSSL-1.0 is required by wkhtmltopdf binary
|
||||
# libreoffice for file preview generation
|
||||
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - && \
|
||||
apt-get update -qq && \
|
||||
apt-get install -y \
|
||||
|
@ -16,6 +19,7 @@ RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - && \
|
|||
default-jre-headless \
|
||||
sudo graphviz --no-install-recommends \
|
||||
libfile-mimeinfo-perl && \
|
||||
apt-get install -y --no-install-recommends -t stretch-backports libreoffice && \
|
||||
npm install -g yarn && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
|
4
Gemfile
4
Gemfile
|
@ -79,8 +79,8 @@ gem 'underscore-rails'
|
|||
gem 'wicked_pdf', '~> 1.1.0'
|
||||
gem 'wkhtmltopdf-heroku'
|
||||
|
||||
gem 'aws-sdk', '~> 2'
|
||||
gem 'paperclip', '~> 5.3' # File attachment, image attachment library
|
||||
gem 'aws-sdk-s3'
|
||||
gem 'paperclip', '~> 6.1' # File attachment, image attachment library
|
||||
gem 'delayed_job_active_record'
|
||||
gem 'devise-async',
|
||||
git: 'https://github.com/mhfs/devise-async.git',
|
||||
|
|
24
Gemfile.lock
24
Gemfile.lock
|
@ -102,13 +102,19 @@ GEM
|
|||
rails (>= 3.1)
|
||||
awesome_print (1.8.0)
|
||||
aws-eventstream (1.0.3)
|
||||
aws-sdk (2.11.264)
|
||||
aws-sdk-resources (= 2.11.264)
|
||||
aws-sdk-core (2.11.264)
|
||||
aws-sigv4 (~> 1.0)
|
||||
aws-partitions (1.172.0)
|
||||
aws-sdk-core (3.54.2)
|
||||
aws-eventstream (~> 1.0, >= 1.0.2)
|
||||
aws-partitions (~> 1.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
jmespath (~> 1.0)
|
||||
aws-sdk-resources (2.11.264)
|
||||
aws-sdk-core (= 2.11.264)
|
||||
aws-sdk-kms (1.21.0)
|
||||
aws-sdk-core (~> 3, >= 3.53.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-s3 (1.42.0)
|
||||
aws-sdk-core (~> 3, >= 3.53.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sigv4 (1.1.0)
|
||||
aws-eventstream (~> 1.0, >= 1.0.2)
|
||||
backports (3.14.0)
|
||||
|
@ -334,7 +340,7 @@ GEM
|
|||
overcommit (0.47.0)
|
||||
childprocess (~> 0.6, >= 0.6.3)
|
||||
iniparse (~> 1.4)
|
||||
paperclip (5.3.0)
|
||||
paperclip (6.1.0)
|
||||
activemodel (>= 4.2.0)
|
||||
activesupport (>= 4.2.0)
|
||||
mime-types
|
||||
|
@ -552,7 +558,7 @@ DEPENDENCIES
|
|||
auto_strip_attributes (~> 2.1)
|
||||
autosize-rails
|
||||
awesome_print
|
||||
aws-sdk (~> 2)
|
||||
aws-sdk-s3
|
||||
base62
|
||||
bcrypt (~> 3.1.10)
|
||||
better_errors
|
||||
|
@ -601,7 +607,7 @@ DEPENDENCIES
|
|||
omniauth
|
||||
omniauth-linkedin-oauth2
|
||||
overcommit
|
||||
paperclip (~> 5.3)
|
||||
paperclip (~> 6.1)
|
||||
pg (~> 0.18)
|
||||
pg_search
|
||||
phantomjs
|
||||
|
|
|
@ -10,16 +10,34 @@ class Asset < ApplicationRecord
|
|||
|
||||
# Paperclip validation
|
||||
has_attached_file :file,
|
||||
styles: {
|
||||
large: [Constants::LARGE_PIC_FORMAT, :jpg],
|
||||
medium: [Constants::MEDIUM_PIC_FORMAT, :jpg],
|
||||
original: { processors: [:image_quality_calculate] }
|
||||
styles: lambda { |a|
|
||||
if a.previewable_document?
|
||||
{
|
||||
large: { processors: [:custom_file_preview],
|
||||
geometry: Constants::LARGE_PIC_FORMAT,
|
||||
format: :jpg },
|
||||
medium: { processors: [:custom_file_preview],
|
||||
geometry: Constants::MEDIUM_PIC_FORMAT,
|
||||
format: :jpg }
|
||||
}
|
||||
else
|
||||
{
|
||||
large: [Constants::LARGE_PIC_FORMAT, :jpg],
|
||||
medium: [Constants::MEDIUM_PIC_FORMAT, :jpg]
|
||||
}
|
||||
end
|
||||
},
|
||||
convert_options: {
|
||||
medium: '-quality 70 -strip',
|
||||
all: '-background "#d2d2d2" -flatten +matte'
|
||||
}
|
||||
|
||||
before_post_process :previewable?
|
||||
before_post_process :extract_image_quality
|
||||
|
||||
# adds image processing in background job
|
||||
process_in_background :file, processing_image_url: '/images/:style/processing.gif'
|
||||
|
||||
validates_attachment :file,
|
||||
presence: true,
|
||||
size: {
|
||||
|
@ -31,20 +49,6 @@ class Asset < ApplicationRecord
|
|||
# Should be checked for any security leaks
|
||||
do_not_validate_attachment_file_type :file
|
||||
|
||||
# adds image processing in background job
|
||||
process_in_background :file,
|
||||
only_process: lambda { |a|
|
||||
if a.content_type ==
|
||||
%r{^image/#{ Regexp.union(
|
||||
Constants::WHITELISTED_IMAGE_TYPES
|
||||
) }}
|
||||
%i(large medium original)
|
||||
else
|
||||
{}
|
||||
end
|
||||
},
|
||||
processing_image_url: '/images/:style/processing.gif'
|
||||
|
||||
# Asset validation
|
||||
# This could cause some problems if you create empty asset and want to
|
||||
# assign it to result
|
||||
|
@ -196,6 +200,22 @@ class Asset < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def extract_image_quality
|
||||
return unless ['image/jpeg', 'image/pjpeg'].include? file_content_type
|
||||
|
||||
tempfile = file.queued_for_write[:original]
|
||||
unless tempfile.nil?
|
||||
quality = Paperclip::Processor.new(tempfile).identify(" -format '%Q' #{tempfile.path}")
|
||||
self.file_image_quality = quality.to_i
|
||||
end
|
||||
rescue StandardError => e
|
||||
Rails.logger.info "There was an error extracting image quality - #{e}"
|
||||
end
|
||||
|
||||
def previewable?
|
||||
file.previewable_image? || file.previewable_document?
|
||||
end
|
||||
|
||||
def is_image?
|
||||
%r{^image/#{Regexp.union(Constants::WHITELISTED_IMAGE_TYPES)}} ===
|
||||
file.content_type
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
<div>
|
||||
<i class="fas fa-10x <%= file_fa_icon_class(asset) %>"></i>
|
||||
<% if asset.file.previewable_document? %>
|
||||
<%= image_tag(asset.url(:large)) %>
|
||||
<% else %>
|
||||
<i class="fas fa-10x <%= file_fa_icon_class(asset) %>"></i>
|
||||
<% end %>
|
||||
<h3 class="file-name"></h3>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<% if asset.file.processing? && asset.is_image? %>
|
||||
<% if asset.file.processing? && (asset.is_image? || asset.file.previewable_document?) %>
|
||||
<% asset_status = 'asset-loading' %>
|
||||
<% present_url = step_file_present_asset_path(asset.id) %>
|
||||
<% else %>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<% image_preview = asset.is_image? ? asset.url(:medium) : nil %>
|
||||
<% image_preview = (asset.is_image? || asset.file.previewable_document?) ? asset.url(:medium) : nil %>
|
||||
|
||||
<div class="attachment-placeholder pull-left">
|
||||
<div class="attachment-thumbnail <%= image_preview ? '' : 'no-shadow' %>">
|
||||
|
|
|
@ -218,6 +218,8 @@ class Constants
|
|||
'text/plain'
|
||||
].freeze
|
||||
|
||||
PREVIEWABLE_FILE_TYPES = TEXT_EXTRACT_FILE_TYPES
|
||||
|
||||
WHITELISTED_IMAGE_TYPES = [
|
||||
'gif', 'jpeg', 'pjpeg', 'png', 'x-png', 'svg+xml', 'bmp', 'tiff'
|
||||
].freeze
|
||||
|
|
|
@ -61,6 +61,27 @@ Paperclip::Attachment.class_eval do
|
|||
def fetch
|
||||
Paperclip.io_adapters.for self
|
||||
end
|
||||
|
||||
def previewable_document?
|
||||
previewable = Constants::PREVIEWABLE_FILE_TYPES.include?(content_type)
|
||||
|
||||
extensions = %w(.xlsx .docx .pptx .xls .doc .ppt)
|
||||
# Mimetype sometimes recognizes Office files as zip files
|
||||
# In this case we also check the extension of the given file
|
||||
# Otherwise the conversion should fail if the file is being something else
|
||||
previewable ||= (content_type == 'application/zip' && extensions.include?(File.extname(original_filename)))
|
||||
|
||||
# Mimetype also sometimes recognizes '.xls' and '.ppt' files as
|
||||
# application/x-ole-storage (https://github.com/minad/mimemagic/issues/50)
|
||||
previewable ||=
|
||||
(content_type == 'application/x-ole-storage' && %w(.xls .ppt).include?(File.extname(original_filename)))
|
||||
|
||||
previewable
|
||||
end
|
||||
|
||||
def previewable_image?
|
||||
content_type =~ %r{^image/#{Regexp.union(Constants::WHITELISTED_IMAGE_TYPES)}}
|
||||
end
|
||||
end
|
||||
|
||||
module Paperclip
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Paperclip
|
||||
class ImageQualityCalculate < Processor
|
||||
def initialize(file, options = {}, attachment = nil)
|
||||
super
|
||||
end
|
||||
|
||||
def make
|
||||
if @file && (['image/jpeg', 'image/pjpeg'].include? @file.content_type)
|
||||
quality = Paperclip::Processor.new(@file).identify(" -format '%Q' #{@file.path}")
|
||||
@attachment.instance.file_image_quality = quality.to_i
|
||||
# Asset will be save after all processors finished
|
||||
end
|
||||
# We need again open file after read quality
|
||||
File.new(File.expand_path(@file.path))
|
||||
rescue StandardError => e
|
||||
raise Paperclip::Error, "There was an error processing the image - #{e}"
|
||||
end
|
||||
end
|
||||
end
|
32
lib/paperclip_processors/custom_file_preview.rb
Normal file
32
lib/paperclip_processors/custom_file_preview.rb
Normal file
|
@ -0,0 +1,32 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Paperclip
|
||||
class CustomFilePreview < Processor
|
||||
def make
|
||||
libreoffice_path = ENV['LIBREOFFICE_PATH'] || 'libreoffice'
|
||||
directory = File.dirname(@file.path)
|
||||
basename = File.basename(@file.path, '.*')
|
||||
original_preview_file = File.join(directory, "#{basename}.png")
|
||||
dst = TempfileFactory.new.generate("#{basename}.#{options[:format]}")
|
||||
|
||||
begin
|
||||
Paperclip.run(
|
||||
libreoffice_path,
|
||||
"--headless --invisible --convert-to png --outdir #{directory} #{@file.path}"
|
||||
)
|
||||
|
||||
convert(
|
||||
":source -resize '#{options[:geometry]}' -format #{options[:format]} #{options[:convert_options]} :dest",
|
||||
source: File.expand_path(original_preview_file),
|
||||
dest: File.expand_path(dst.path)
|
||||
)
|
||||
ensure
|
||||
File.delete(original_preview_file) if File.file?(original_preview_file)
|
||||
end
|
||||
|
||||
dst
|
||||
rescue StandardError => e
|
||||
raise Paperclip::Error, "There was an error generating document preview - #{e}"
|
||||
end
|
||||
end
|
||||
end
|
BIN
public/images/large/processing.gif
Normal file
BIN
public/images/large/processing.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
Loading…
Reference in a new issue