このコミットが含まれているのは:
@@ -13,6 +13,46 @@ class CountsExportDownload
|
||||
class TimedOut < StandardError; end
|
||||
class StorageFull < StandardError; end
|
||||
|
||||
# Rack body deliberately has no to_path: sendfile middleware must not bypass ACK.
|
||||
class ResponseBody
|
||||
def initialize(path, &state)
|
||||
File.open(path, 'rb') { |file| file.stat }
|
||||
@path = path
|
||||
@stream = nil
|
||||
@closed = false
|
||||
@state = state
|
||||
end
|
||||
|
||||
def each
|
||||
return if @closed
|
||||
|
||||
@stream = File.open(@path, 'rb')
|
||||
first = true
|
||||
while (chunk = @stream.read(64 * 1024))
|
||||
raise IOError, 'Download no longer authorised' unless @state.call('active')
|
||||
|
||||
yield chunk
|
||||
if first
|
||||
# This confirms yielding to Rack, never browser receipt or saving.
|
||||
@state.call('started')
|
||||
first = false
|
||||
end
|
||||
end
|
||||
@state.call('failed') if first
|
||||
rescue StandardError => error
|
||||
Rails.logger.warn("counts_download_stream_failure: #{ error.class }")
|
||||
@state.call('failed')
|
||||
raise
|
||||
ensure
|
||||
close
|
||||
end
|
||||
|
||||
def close
|
||||
@closed = true
|
||||
@stream.close if @stream && !@stream.closed?
|
||||
end
|
||||
end
|
||||
|
||||
def self.directory
|
||||
Rails.root.join(ENV.fetch('COUNTS_EXPORT_DIRECTORY', 'tmp/counts_exports'))
|
||||
end
|
||||
|
||||
新しいイシューから参照
ユーザーをブロックする