Module: ZipKit::RailsStreaming

Defined in:
lib/zip_kit/rails_streaming.rb

Overview

Should be included into a Rails controller for easy ZIP output from any action.

Instance Method Summary collapse

Instance Method Details

#zip_kit_stream(filename: "download.zip", type: "application/zip", **zip_streamer_options) {|Streamer| ... } ⇒ ZipKit::OutputEnumerator

Opens a Streamer and yields it to the caller. The output of the streamer gets automatically forwarded to the Rails response stream. When the output completes, the Rails response stream is going to be closed automatically.

Parameters:

  • filename (String) (defaults to: "download.zip")

    name of the file for the Content-Disposition header

  • type (String) (defaults to: "application/zip")

    the content type (MIME type) of the archive being output

  • zip_streamer_options (Hash)

    options that will be passed to the Streamer. See Streamer#initialize for the full list of options.

Yields:

  • (Streamer)

    the streamer that can be written to

Returns:



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/zip_kit/rails_streaming.rb', line 14

def zip_kit_stream(filename: "download.zip", type: "application/zip", **zip_streamer_options, &zip_streaming_blk)
  # The output enumerator yields chunks of bytes generated from ZipKit. Instantiating it
  # first will also validate the Streamer options.
  chunk_yielder = ZipKit::OutputEnumerator.new(**zip_streamer_options, &zip_streaming_blk)

  # We want some common headers for file sending. Rails will also set
  # self.sending_file = true for us when we call send_file_headers!
  send_file_headers!(type: type, filename: filename)

  # Check for the proxy configuration first. This is the first common misconfiguration which destroys streaming -
  # since HTTP 1.0 does not support chunked responses we need to revert to buffering. The issue though is that
  # this reversion happens silently and it is usually not clear at all why streaming does not work. So let's at
  # the very least print it to the Rails log.
  if request.get_header("HTTP_VERSION") == "HTTP/1.0"
    logger&.warn { "The downstream HTTP proxy/LB insists on HTTP/1.0 protocol, ZIP response will be buffered." }
  end

  headers, rack_body = chunk_yielder.to_headers_and_rack_response_body(request.env)

  # Set the "particular" streaming headers
  response.headers.merge!(headers)
  self.response_body = rack_body
end