response_with_limit_adapter.rb 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. # frozen_string_literal: true
  2. module Paperclip
  3. class ResponseWithLimitAdapter < AbstractAdapter
  4. def self.register
  5. Paperclip.io_adapters.register self do |target|
  6. target.is_a?(ResponseWithLimit)
  7. end
  8. end
  9. def initialize(target, options = {})
  10. super
  11. cache_current_values
  12. end
  13. private
  14. def cache_current_values
  15. @original_filename = filename_from_content_disposition.presence || filename_from_path.presence || 'data'
  16. @size = @target.response.content_length
  17. @tempfile = copy_to_tempfile(@target)
  18. @content_type = ContentTypeDetector.new(@tempfile.path).detect
  19. end
  20. def copy_to_tempfile(source)
  21. bytes_read = 0
  22. source.response.body.each do |chunk|
  23. bytes_read += chunk.bytesize
  24. destination.write(chunk)
  25. chunk.clear
  26. raise Mastodon::LengthValidationError if bytes_read > source.limit
  27. end
  28. destination.rewind
  29. destination
  30. rescue Mastodon::LengthValidationError
  31. destination.close(true)
  32. raise
  33. ensure
  34. source.response.connection.close
  35. end
  36. def filename_from_content_disposition
  37. disposition = @target.response.headers['content-disposition']
  38. disposition&.match(/filename="([^"]*)"/)&.captures&.first
  39. end
  40. def filename_from_path
  41. @target.response.uri.path.split('/').last
  42. end
  43. end
  44. end