Class: Zipline::ZipGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/zipline/zip_generator.rb

Instance Method Summary collapse

Constructor Details

#initialize(files, **kwargs_for_new) ⇒ ZipGenerator

takes an array of pairs [[uploader, filename], … ]



6
7
8
9
# File 'lib/zipline/zip_generator.rb', line 6

def initialize(files,  **kwargs_for_new)
  @files = files
  @kwargs_for_new = kwargs_for_new
end

Instance Method Details

#each(&block) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/zipline/zip_generator.rb', line 16

def each(&block)
  fake_io_writer = ZipTricks::BlockWrite.new(&block)
  # ZipTricks outputs lots of strings in rapid succession, and with
  # servers it can be beneficial to avoid doing too many tiny writes so that
  # the number of syscalls is minimized. See https://github.com/WeTransfer/zip_tricks/issues/78
  # There is a built-in facility for this in ZipTricks which can be used to implement
  # some cheap buffering here (it exists both in version 4 and version 5). The buffer is really
  # tiny and roughly equal to the medium Linux socket buffer size (16 KB). Although output
  # will be not so immediate with this buffering the overall performance will be better,
  # especially with multiple clients being serviced at the same time.
  # Note that the WriteBuffer writes the same, retained String object - but the contents
  # of that object changes between calls. This should work fine with servers where the
  # contents of the string gets written to a socket immediately before the execution inside
  # the WriteBuffer resumes), but if the strings get retained somewhere - like in an Array -
  # this might pose a problem. Unlikely that it will be an issue here though.
  write_buffer_size = 16 * 1024
  write_buffer = ZipTricks::WriteBuffer.new(fake_io_writer, write_buffer_size)
  ZipTricks::Streamer.open(write_buffer, **@kwargs_for_new) do |streamer|
    @files.each do |file, name, options = {}|
      handle_file(streamer, file, name.to_s, options)
    end
  end
  write_buffer.flush! # for any remaining writes
end

#handle_file(streamer, file, name, options) ⇒ Object



41
42
43
44
# File 'lib/zipline/zip_generator.rb', line 41

def handle_file(streamer, file, name, options)
  file = normalize(file)
  write_file(streamer, file, name, options)
end

#is_io?(io_ish) ⇒ Boolean

Returns:

  • (Boolean)


104
105
106
# File 'lib/zipline/zip_generator.rb', line 104

def is_io?(io_ish)
  io_ish.respond_to? :read
end

#normalize(file) ⇒ Object

This extracts either a url or a local file from the provided file. Currently support carrierwave and paperclip local and remote storage. returns a hash of the form aUrl or anIoObject



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/zipline/zip_generator.rb', line 49

def normalize(file)
  if defined?(CarrierWave::Uploader::Base) && file.is_a?(CarrierWave::Uploader::Base)
    file = file.file
  end

  if defined?(Paperclip) && file.is_a?(Paperclip::Attachment)
    if file.options[:storage] == :filesystem
      {file: File.open(file.path)}
    else
      {url: file.expiring_url}
    end
  elsif defined?(CarrierWave::Storage::Fog::File) && file.is_a?(CarrierWave::Storage::Fog::File)
    {url: file.url}
  elsif defined?(CarrierWave::SanitizedFile) && file.is_a?(CarrierWave::SanitizedFile)
    {file: File.open(file.path)}
  elsif is_io?(file)
    {file: file}
  elsif defined?(ActiveStorage::Blob) && file.is_a?(ActiveStorage::Blob)
    {blob: file}
  elsif is_active_storage_attachment?(file) || is_active_storage_one?(file)
    {blob: file.blob}
  elsif file.respond_to? :url
    {url: file.url}
  elsif file.respond_to? :path
    {file: File.open(file.path)}
  elsif file.respond_to? :file
    {file: File.open(file.file)}
  elsif is_url?(file)
    {url: file}
  else
    raise(ArgumentError, 'Bad File/Stream')
  end
end

#to_sObject

this is supposed to be streamed!



12
13
14
# File 'lib/zipline/zip_generator.rb', line 12

def to_s
  throw "stop!"
end

#write_file(streamer, file, name, options) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/zipline/zip_generator.rb', line 83

def write_file(streamer, file, name, options)
  streamer.write_deflated_file(name, **options.slice(:modification_time)) do |writer_for_file|
    if file[:url]
      the_remote_uri = URI(file[:url])

      Net::HTTP.get_response(the_remote_uri) do |response|
        response.read_body do |chunk|
          writer_for_file << chunk
        end
      end
    elsif file[:file]
      IO.copy_stream(file[:file], writer_for_file)
      file[:file].close
    elsif file[:blob]
      file[:blob].download { |chunk| writer_for_file << chunk }
    else
      raise(ArgumentError, 'Bad File/Stream')
    end
  end
end