uploads: use storage manager to distribute files.

Refactors the upload process to pass around temp files, rather than
passing around file paths and directly writing output to the local
filesystem. This way we can pass the storage manager the preview /
sample / original temp files, so it can deal with storage itself.

* Change Download::File#download! to return a temp file.

* Change DanbooruImageResizer and PixivUgoiraConverter to accept/return
  temp files instead of file paths.

* Change Upload#generate_resizes to return temp files for previews and samples.

* Change Upload#generate_resizes to generate ugoira .webm samples
  synchronously instead of asynchronously.
This commit is contained in:
evazion
2018-03-18 12:05:25 -05:00
parent 60dcfbfbdd
commit c76463f34d
8 changed files with 89 additions and 183 deletions

View File

@@ -1,6 +1,6 @@
module DanbooruImageResizer
def resize(read_path, write_path, width, height, resize_quality = 90)
image = Magick::Image.read(read_path).first
def resize(file, width, height, resize_quality = 90)
image = Magick::Image.read(file.path).first
geometry = "#{width}x>"
if width == Danbooru.config.small_image_width
@@ -17,14 +17,15 @@ module DanbooruImageResizer
image = flatten(image, width, height)
image.strip!
image.write(write_path) do
output_file = Tempfile.new(binmode: true)
image.write("jpeg:" + output_file.path) do
self.quality = resize_quality
# setting PlaneInterlace enables progressive encoding for JPEGs
self.interlace = Magick::PlaneInterlace
end
image.destroy!
FileUtils.chmod(0664, write_path)
output_file
end
def flatten(image, width, height)

View File

@@ -3,9 +3,9 @@ module Downloads
class Error < Exception ; end
attr_reader :data, :options
attr_accessor :source, :original_source, :downloaded_source, :file_path
attr_accessor :source, :original_source, :downloaded_source
def initialize(source, file_path, options = {})
def initialize(source, options = {})
# source can potentially get rewritten in the course
# of downloading a file, so check it again
@source = source
@@ -14,9 +14,6 @@ module Downloads
# the URL actually downloaded after rewriting the original source.
@downloaded_source = nil
# where to save the download
@file_path = file_path
# we sometimes need to capture data from the source page
@data = {}
@@ -35,12 +32,13 @@ module Downloads
def download!
url, headers, @data = before_download(@source, @data)
::File.open(@file_path, "wb") do |out|
http_get_streaming(uncached_url(url, headers), out, headers)
end
output_file = Tempfile.new(binmode: true)
http_get_streaming(uncached_url(url, headers), output_file, headers)
@downloaded_source = url
@source = after_download(url)
output_file
end
def before_download(url, datums)
@@ -91,7 +89,8 @@ module Downloads
end
if res.success?
return
file.rewind
return file
else
raise Error.new("HTTP error code: #{res.code} #{res.message}")
end

View File

@@ -1,13 +1,9 @@
class PixivUgoiraConverter
def self.convert(source_path, output_path, preview_path, frame_data)
folder = Zip::File.new(source_path)
write_webm(folder, output_path, frame_data)
write_preview(folder, preview_path)
RemoteFileManager.new(output_path).distribute
RemoteFileManager.new(preview_path).distribute
end
def self.generate_webm(ugoira_file, frame_data)
folder = Zip::File.new(ugoira_file.path)
output_file = Tempfile.new(binmode: true)
write_path = output_file.path
def self.write_webm(folder, write_path, frame_data)
Dir.mktmpdir do |tmpdir|
FileUtils.mkdir_p("#{tmpdir}/images")
folder.each_with_index do |file, i|
@@ -64,14 +60,17 @@ class PixivUgoiraConverter
return
end
end
output_file
end
def self.write_preview(folder, path)
Dir.mktmpdir do |tmpdir|
file = folder.first
temp_path = File.join(tmpdir, file.name)
file.extract(temp_path)
DanbooruImageResizer.resize(temp_path, path, Danbooru.config.small_image_width, Danbooru.config.small_image_width, 85)
end
def self.generate_preview(ugoira_file)
file = Tempfile.new(binmode: true)
zipfile = Zip::File.new(ugoira_file.path)
zipfile.entries.first.extract(file.path) { true } # 'true' means overwrite the existing tempfile.
DanbooruImageResizer.resize(file, Danbooru.config.small_image_width, Danbooru.config.small_image_width, 85)
ensure
file.close!
end
end

View File

@@ -1,32 +1,10 @@
class PixivUgoiraService
attr_reader :width, :height, :frame_data, :content_type
def self.regen(post)
service = new()
service.load(
:is_ugoira => true,
:ugoira_frame_data => post.pixiv_ugoira_frame_data.data
)
service.generate_resizes(post.file_path, post.large_file_path, post.preview_file_path, false)
end
def save_frame_data(post)
PixivUgoiraFrameData.create(:data => @frame_data, :content_type => @content_type, :post_id => post.id)
end
def generate_resizes(source_path, output_path, preview_path, delay = true)
# Run this a bit in the future to give the upload process time to move the file
if delay
PixivUgoiraConverter.delay(:queue => Socket.gethostname, :run_at => 10.seconds.from_now, :priority => -1).convert(source_path, output_path, preview_path, @frame_data)
else
PixivUgoiraConverter.convert(source_path, output_path, preview_path, @frame_data)
end
# since the resizes will be delayed, just touch the output file so the
# file distribution wont break
FileUtils.touch([output_path, preview_path])
end
def calculate_dimensions(source_path)
folder = Zip::File.new(source_path)
tempfile = Tempfile.new("ugoira-dimensions")