Module: Dommy::Rack::FileUpload
- Defined in:
- lib/dommy/rack/file_upload.rb
Overview
Encodes collected form params (ordered [name, value] pairs) as a multipart/form-data body. File/Blob values become file parts; other values become text parts. Owns the multipart serialization so the HTTP layer (not Dommy::FormData) is responsible for it.
Constant Summary collapse
- MIME_TYPES =
{ ".txt" => "text/plain", ".html" => "text/html", ".htm" => "text/html", ".json" => "application/json", ".csv" => "text/csv", ".xml" => "application/xml", ".png" => "image/png", ".jpg" => "image/jpeg", ".jpeg" => "image/jpeg", ".gif" => "image/gif", ".pdf" => "application/pdf" }.freeze
Class Method Summary collapse
-
.encode(pairs, boundary = nil) ⇒ Object
Returns [body (ASCII-8BIT String), content_type with boundary].
- .escape(str) ⇒ Object
- .file_content_type(value) ⇒ Object
-
.mime_type_for(path) ⇒ Object
Guess a MIME type from a file path’s extension.
-
.multipart?(pairs) ⇒ Boolean
True when any pair value is a File/Blob.
- .part(boundary, name, value) ⇒ Object
Class Method Details
.encode(pairs, boundary = nil) ⇒ Object
Returns [body (ASCII-8BIT String), content_type with boundary].
41 42 43 44 45 46 47 |
# File 'lib/dommy/rack/file_upload.rb', line 41 def encode(pairs, boundary = nil) boundary ||= "----DommyRackBoundary#{SecureRandom.hex(16)}" body = +"".b pairs.each { |name, value| body << part(boundary, name, value) } body << "--#{boundary}--\r\n" [body, "multipart/form-data; boundary=#{boundary}"] end |
.escape(str) ⇒ Object
68 69 70 |
# File 'lib/dommy/rack/file_upload.rb', line 68 def escape(str) str.to_s.gsub('"', "%22").gsub(/[\r\n]/, "") end |
.file_content_type(value) ⇒ Object
63 64 65 66 |
# File 'lib/dommy/rack/file_upload.rb', line 63 def file_content_type(value) type = value.respond_to?(:type) ? value.type.to_s : "" type.empty? ? "application/octet-stream" : type end |
.mime_type_for(path) ⇒ Object
Guess a MIME type from a file path’s extension.
29 30 31 |
# File 'lib/dommy/rack/file_upload.rb', line 29 def mime_type_for(path) MIME_TYPES.fetch(::File.extname(path).downcase, "application/octet-stream") end |
.multipart?(pairs) ⇒ Boolean
True when any pair value is a File/Blob.
34 35 36 37 38 |
# File 'lib/dommy/rack/file_upload.rb', line 34 def multipart?(pairs) return false unless pairs pairs.any? { |(_name, value)| value.respond_to?(:__dommy_bytes__) } end |
.part(boundary, name, value) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/dommy/rack/file_upload.rb', line 49 def part(boundary, name, value) head = +"--#{boundary}\r\n" if value.respond_to?(:__dommy_bytes__) # File / Blob filename = value.respond_to?(:name) ? value.name.to_s : "" content_type = file_content_type(value) head << %(Content-Disposition: form-data; name="#{escape(name)}"; filename="#{escape(filename)}"\r\n) head << "Content-Type: #{content_type}\r\n\r\n" head.b << value.__dommy_bytes__ << "\r\n".b else head << %(Content-Disposition: form-data; name="#{escape(name)}"\r\n\r\n) head.b << value.to_s.dup.force_encoding(Encoding::ASCII_8BIT) << "\r\n".b end end |