1616
1717/**
1818 * Helper for submitting multipart data
19- *
20- * This follows the Network Working Group's RFC
19+ *
20+ * This follows the Network Working Group's RFC
2121 * on multipart/form-data posting format:
2222 * https://www.ietf.org/rfc/rfc2388.txt
2323 */
@@ -28,15 +28,15 @@ public class Multipart {
2828 /** Default encoding for multi-part requests */
2929 public static final String MULTIPART_ENCODING = "US-ASCII" ;
3030 private String contentType = "multipart/form-data" ;
31-
31+
3232 /**
3333 * Create a new multipart object
3434 */
3535 public Multipart () {
3636 out = new ByteArrayOutputStream ();
3737 boundary = "part_" + new BigInteger (130 , new SecureRandom ()).toString ();
3838 }
39-
39+
4040 /**
4141 * Get the multipart boundary for use in the request header
4242 * @return the multipart boundary
@@ -45,15 +45,15 @@ public Multipart() {
4545 public String getBoundary () {
4646 return boundary ;
4747 }
48-
48+
4949 /**
5050 * Set the multipart boundary for use in the request header
5151 * @param boundary The multipart boundary
5252 */
5353 public void setBoundary (@ Nonnull final String boundary ) {
5454 this .boundary = boundary ;
5555 }
56-
56+
5757 /**
5858 * Get the contentType for use in the request header
5959 * @return the multipart Content-Type
@@ -62,15 +62,15 @@ public void setBoundary(@Nonnull final String boundary) {
6262 public String getContentType () {
6363 return contentType ;
6464 }
65-
65+
6666 /**
6767 * Set the contentType for use in the request header
6868 * @param contentType The multipart Content-Type
6969 */
7070 public void setContentType (@ Nonnull final String contentType ) {
7171 this .contentType = contentType ;
7272 }
73-
73+
7474 /**
7575 * Get the Content-Type header to send the multipart request
7676 * @return the multipart header option
@@ -79,72 +79,71 @@ public void setContentType(@Nonnull final String contentType) {
7979 public HeaderOption header () {
8080 return new HeaderOption ("Content-Type" , contentType + "; boundary=\" " + boundary + "\" " );
8181 }
82-
82+
8383 private void writePartData (String partContent , byte [] byteArray ) throws IOException {
8484 out .write (partContent .getBytes (MULTIPART_ENCODING ));
8585 out .write (byteArray );
8686 String returnContent = RETURN + RETURN ;
8787 out .write (returnContent .getBytes (MULTIPART_ENCODING ));
8888 }
89-
89+
9090 /**
9191 * Create content headers value and parameter
9292 * @param name The content header name
9393 * @param contentType The content header Content-Type
94- * @param filename The content header filename
95- * @return content header value and parameter string
94+ * @param filename The content header filename
95+ * @return content header value and parameter string
9696 */
9797 @ VisibleForTesting
9898 String createPartHeader (String name , String contentType , String filename ) {
9999 StringBuilder partContent = new StringBuilder (addBoundary ());
100100 partContent .append ("Content-Disposition: form-data" );
101101 if (filename != null ) {
102- if (name != null )
102+ if (name != null )
103103 partContent .append ("; name=\" " ).append (name ).append ("\" ; filename=\" " ).append (filename ).append ("\" " );
104- else
104+ else
105105 partContent .append ("; filename=\" " ).append (filename ).append ("\" " );
106106 }
107- else if (name != null )
107+ else if (name != null )
108108 partContent .append ("; name=\" " ).append (name ).append ("\" " );
109109 if (contentType != null )
110110 partContent .append (RETURN ).append ("Content-Type: " ).append (contentType );
111111 partContent .append (RETURN ).append (RETURN );
112112 return partContent .toString ();
113113 }
114-
114+
115115 /**
116116 * Create content headers value and parameter
117117 * @param contentValue The content header value
118- * @param contentDispParameter Map containing content paramter's key and value pair
119- * @return content header value and parameter string
118+ * @param contentDispParameter Map containing content paramter's key and value pair
119+ * @return content header value and parameter string
120120 */
121121 @ Nonnull
122122 public static String createContentHeaderValue (@ Nonnull final String contentValue , @ Nullable final Map <String , String > contentDispParameter ) {
123- String contentHeaderValue = contentValue ;
123+ final StringBuilder builder = new StringBuilder ( contentValue ) ;
124124
125125 if (contentDispParameter != null ) {
126126 for (Map .Entry <String ,String > entry : contentDispParameter .entrySet ())
127- contentHeaderValue += ";" + entry .getKey () + "=\" " + entry .getValue () + "\" " ;
127+ builder . append ( ";" + entry .getKey () + "=\" " + entry .getValue () + "\" " ) ;
128128 }
129- return contentHeaderValue ;
129+ return builder . toString () ;
130130 }
131-
131+
132132 /**
133133 * Create content headers header-name, value and parameter string
134134 * @param headers Map containing Header-name and header-value pair
135135 */
136136 private String createPartHeader (Map <String , String > headers ) {
137- String partContent = addBoundary ();
138- String defaultPartContent = "Content-Disposition: form-data;" + RETURN + "Content-Type: " + contentType + RETURN + RETURN ;
139-
140- if (headers != null ) {
141- for (Map .Entry <String ,String > entry : headers .entrySet ())
142- partContent += entry .getKey () +": " +entry .getValue () + RETURN ;
143- partContent += RETURN ;
144- }
145- else
146- partContent += defaultPartContent ;
147- return partContent ;
137+ final StringBuilder builder = new StringBuilder (addBoundary ());
138+ final String defaultPartContent = "Content-Disposition: form-data;" + RETURN + "Content-Type: " + contentType + RETURN + RETURN ;
139+
140+ if (headers != null ) {
141+ for (Map .Entry <String ,String > entry : headers .entrySet ())
142+ builder .append (entry .getKey () +": " +entry .getValue () + RETURN );
143+ builder .append (RETURN );
144+ } else
145+ builder .append (defaultPartContent );
146+ return builder .toString ();
148147 }
149148
150149 /**
@@ -170,7 +169,7 @@ private void addData(String name, String contentType, String filename, byte[] by
170169 public void addFormData (@ Nonnull final String name , @ Nonnull final String contentType , @ Nonnull final byte [] byteArray ) throws IOException {
171170 addData (name , contentType , null , byteArray );
172171 }
173-
172+
174173 /**
175174 * Add a part to the multipart body
176175 * @param contentType The MIME type (text/html, video/mp4, etc.)
@@ -180,7 +179,7 @@ public void addFormData(@Nonnull final String name, @Nonnull final String conten
180179 public void addPart (@ Nonnull final String contentType , @ Nonnull final byte [] byteArray ) throws IOException {
181180 addData (null , contentType , null , byteArray );
182181 }
183-
182+
184183 /**
185184 * Add a part to the multipart body
186185 * @param headers Map containing Header's header-name(eg: Content-Disposition, Content-Type, etc..) and header's value-parameter string
@@ -191,7 +190,7 @@ public void addPart(@Nonnull final Map<String, String> headers, @Nonnull final b
191190 final String partContent = createPartHeader (headers );
192191 writePartData (partContent , content );
193192 }
194-
193+
195194 /**
196195 * Add an HTML part to the multipart body
197196 * @param name The name of the part
@@ -201,7 +200,7 @@ public void addPart(@Nonnull final Map<String, String> headers, @Nonnull final b
201200 public void addHtmlPart (@ Nonnull final String name , @ Nonnull final byte [] content ) throws IOException {
202201 addFormData (name , "text/html" , content );
203202 }
204-
203+
205204 /**
206205 * Add a file part to the multipart body
207206 * @param name The name of the part
@@ -210,27 +209,28 @@ public void addHtmlPart(@Nonnull final String name, @Nonnull final byte[] conten
210209 * @throws IOException Throws an exception if the output stream cannot be written to
211210 */
212211 public void addFilePart (@ Nonnull final String name , @ Nonnull final String contentType , @ Nonnull final java .io .File file ) throws IOException {
213- final InputStream fileStream = new FileInputStream (file );
214- final byte [] fileBytes = getByteArray (fileStream );
215- addData (name , contentType , file .getName (), fileBytes );
212+ try (final InputStream fileStream = new FileInputStream (file )) {
213+ final byte [] fileBytes = getByteArray (fileStream );
214+ addData (name , contentType , file .getName (), fileBytes );
215+ }
216216 }
217-
217+
218218 /**
219219 * Adds a boundary at the beginning of a new part
220220 * @return The boundary
221221 */
222222 private String addBoundary () {
223223 return "--" + boundary + RETURN ;
224224 }
225-
225+
226226 /**
227227 * Adds a boundary at the end of the multipart body
228228 * @return The boundary
229229 */
230230 private String addEnding () {
231231 return "--" + boundary + "--" ;
232232 }
233-
233+
234234 /**
235235 * Returns a full multipart body byte array
236236 * @return The byte[] representation of the multipart object
@@ -242,7 +242,7 @@ public byte[] content() throws IOException {
242242 finalStream .write (addEnding ().getBytes (MULTIPART_ENCODING ));
243243 return finalStream .toByteArray ();
244244 }
245-
245+
246246 /**
247247 * Helper method to convert an InputStream to a byte[]
248248 * @param in The input stream to convert
0 commit comments