1+ # frozen_string_literal: true
2+
3+ module Square
4+ # FileParam is a utility class for handling files in multipart form data.
5+ #
6+ # @attr_reader [IO] io The readable object
7+ # @attr_reader [String, nil] filename The filename
8+ # @attr_reader [String, nil] content_type The content type
9+ class FileParam
10+ attr_reader :io , :filename , :content_type
11+
12+ # Create a new file parameter.
13+ #
14+ # @param io [#read] A readable object (File, StringIO, etc.)
15+ # @param filename [String, nil] Optional filename
16+ # @param content_type [String, nil] Optional content type
17+ def initialize ( io :, filename : nil , content_type : nil )
18+ @io = io
19+ @filename = filename
20+ @content_type = content_type
21+ end
22+
23+ # Creates a FileParam instance from a filepath.
24+ #
25+ # @param filepath [String] Path to the file
26+ # @param filename [String, nil] Optional filename (defaults to basename of filepath)
27+ # @param content_type [String, nil] Optional content type
28+ # @return [FileParam] A new FileParam instance
29+ # @raise [StandardError] If the file cannot be opened or read
30+ def self . from_filepath ( filepath :, filename : nil , content_type : nil )
31+ begin
32+ file = File . open ( filepath , "rb" )
33+ rescue StandardError => e
34+ raise "Unable to open file #{ filepath } : #{ e . message } "
35+ end
36+
37+ new (
38+ io : file ,
39+ filename : filename || File . basename ( filepath ) ,
40+ content_type : content_type
41+ )
42+ end
43+
44+ # Creates a FileParam instance from a string.
45+ #
46+ # @param content [String] The content string
47+ # @param filename [String, nil] Required filename
48+ # @param content_type [String, nil] Optional content type
49+ # @return [FileParam] A new FileParam instance
50+ def self . from_string ( content :, filename :, content_type : nil )
51+ new (
52+ io : StringIO . new ( content ) ,
53+ filename : filename ,
54+ content_type : content_type
55+ )
56+ end
57+
58+ # Maps this FileParam to a FormDataPart.
59+ #
60+ # @param name [String] The name of the form field
61+ # @param content_type [String, nil] Overrides the content type, if provided
62+ # @return [Square::Internal::Multipart::FormDataPart] A multipart form data part representing this file
63+ def to_form_data_part ( name :, content_type : nil )
64+ content_type ||= @content_type
65+ headers = content_type ? { "Content-Type" => content_type } : nil
66+
67+ Square ::Internal ::Multipart ::FormDataPart . new (
68+ name : name ,
69+ value : @io ,
70+ filename : @filename ,
71+ headers : headers
72+ )
73+ end
74+
75+ # Closes the file IO if it responds to close.
76+ #
77+ # @return [nil]
78+ def close
79+ @io . close if @io . respond_to? ( :close )
80+ nil
81+ end
82+ end
83+ end
0 commit comments