1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.http.entity.mime;
29
30 import java.io.File;
31 import java.io.InputStream;
32 import java.nio.charset.Charset;
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.List;
36 import java.util.Random;
37
38 import org.apache.http.HttpEntity;
39 import org.apache.http.NameValuePair;
40 import org.apache.http.entity.ContentType;
41 import org.apache.http.entity.mime.content.ByteArrayBody;
42 import org.apache.http.entity.mime.content.ContentBody;
43 import org.apache.http.entity.mime.content.FileBody;
44 import org.apache.http.entity.mime.content.InputStreamBody;
45 import org.apache.http.entity.mime.content.StringBody;
46 import org.apache.http.message.BasicNameValuePair;
47 import org.apache.http.util.Args;
48
49
50
51
52
53
54 public class MultipartEntityBuilder {
55
56
57
58
59 private final static char[] MULTIPART_CHARS =
60 "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
61 .toCharArray();
62
63 private final static String DEFAULT_SUBTYPE = "form-data";
64
65 private ContentType contentType;
66 private HttpMultipartMode mode = HttpMultipartMode.STRICT;
67 private String boundary = null;
68 private Charset charset = null;
69 private List<FormBodyPart> bodyParts = null;
70
71 public static MultipartEntityBuilder create() {
72 return new MultipartEntityBuilder();
73 }
74
75 MultipartEntityBuilder() {
76 }
77
78 public MultipartEntityBuilder setMode(final HttpMultipartMode mode) {
79 this.mode = mode;
80 return this;
81 }
82
83 public MultipartEntityBuilder setLaxMode() {
84 this.mode = HttpMultipartMode.BROWSER_COMPATIBLE;
85 return this;
86 }
87
88 public MultipartEntityBuilder setStrictMode() {
89 this.mode = HttpMultipartMode.STRICT;
90 return this;
91 }
92
93 public MultipartEntityBuilder setBoundary(final String boundary) {
94 this.boundary = boundary;
95 return this;
96 }
97
98
99
100
101 public MultipartEntityBuilder setMimeSubtype(final String subType) {
102 Args.notBlank(subType, "MIME subtype");
103 this.contentType = ContentType.create("multipart/" + subType);
104 return this;
105 }
106
107
108
109
110
111
112 @Deprecated
113 public MultipartEntityBuilder seContentType(final ContentType contentType) {
114 return setContentType(contentType);
115 }
116
117
118
119
120 public MultipartEntityBuilder setContentType(final ContentType contentType) {
121 Args.notNull(contentType, "Content type");
122 this.contentType = contentType;
123 return this;
124 }
125
126 public MultipartEntityBuilder setCharset(final Charset charset) {
127 this.charset = charset;
128 return this;
129 }
130
131
132
133
134 public MultipartEntityBuilder addPart(final FormBodyPart bodyPart) {
135 if (bodyPart == null) {
136 return this;
137 }
138 if (this.bodyParts == null) {
139 this.bodyParts = new ArrayList<FormBodyPart>();
140 }
141 this.bodyParts.add(bodyPart);
142 return this;
143 }
144
145 public MultipartEntityBuilder addPart(final String name, final ContentBody contentBody) {
146 Args.notNull(name, "Name");
147 Args.notNull(contentBody, "Content body");
148 return addPart(FormBodyPartBuilder.create(name, contentBody).build());
149 }
150
151 public MultipartEntityBuilder addTextBody(
152 final String name, final String text, final ContentType contentType) {
153 return addPart(name, new StringBody(text, contentType));
154 }
155
156 public MultipartEntityBuilder addTextBody(
157 final String name, final String text) {
158 return addTextBody(name, text, ContentType.DEFAULT_TEXT);
159 }
160
161 public MultipartEntityBuilder addBinaryBody(
162 final String name, final byte[] b, final ContentType contentType, final String filename) {
163 return addPart(name, new ByteArrayBody(b, contentType, filename));
164 }
165
166 public MultipartEntityBuilder addBinaryBody(
167 final String name, final byte[] b) {
168 return addBinaryBody(name, b, ContentType.DEFAULT_BINARY, null);
169 }
170
171 public MultipartEntityBuilder addBinaryBody(
172 final String name, final File file, final ContentType contentType, final String filename) {
173 return addPart(name, new FileBody(file, contentType, filename));
174 }
175
176 public MultipartEntityBuilder addBinaryBody(
177 final String name, final File file) {
178 return addBinaryBody(name, file, ContentType.DEFAULT_BINARY, file != null ? file.getName() : null);
179 }
180
181 public MultipartEntityBuilder addBinaryBody(
182 final String name, final InputStream stream, final ContentType contentType,
183 final String filename) {
184 return addPart(name, new InputStreamBody(stream, contentType, filename));
185 }
186
187 public MultipartEntityBuilder addBinaryBody(final String name, final InputStream stream) {
188 return addBinaryBody(name, stream, ContentType.DEFAULT_BINARY, null);
189 }
190
191 private String generateBoundary() {
192 final StringBuilder buffer = new StringBuilder();
193 final Random rand = new Random();
194 final int count = rand.nextInt(11) + 30;
195 for (int i = 0; i < count; i++) {
196 buffer.append(MULTIPART_CHARS[rand.nextInt(MULTIPART_CHARS.length)]);
197 }
198 return buffer.toString();
199 }
200
201 MultipartFormEntity buildEntity() {
202 String boundaryCopy = boundary;
203 if (boundaryCopy == null && contentType != null) {
204 boundaryCopy = contentType.getParameter("boundary");
205 }
206 if (boundaryCopy == null) {
207 boundaryCopy = generateBoundary();
208 }
209 Charset charsetCopy = charset;
210 if (charsetCopy == null && contentType != null) {
211 charsetCopy = contentType.getCharset();
212 }
213 final List<NameValuePair> paramsList = new ArrayList<NameValuePair>(2);
214 paramsList.add(new BasicNameValuePair("boundary", boundaryCopy));
215 if (charsetCopy != null) {
216 paramsList.add(new BasicNameValuePair("charset", charsetCopy.name()));
217 }
218 final NameValuePair[] params = paramsList.toArray(new NameValuePair[paramsList.size()]);
219 final ContentType contentTypeCopy = contentType != null ?
220 contentType.withParameters(params) :
221 ContentType.create("multipart/" + DEFAULT_SUBTYPE, params);
222 final List<FormBodyPart> bodyPartsCopy = bodyParts != null ? new ArrayList<FormBodyPart>(bodyParts) :
223 Collections.<FormBodyPart>emptyList();
224 final HttpMultipartMode modeCopy = mode != null ? mode : HttpMultipartMode.STRICT;
225 final AbstractMultipartForm form;
226 switch (modeCopy) {
227 case BROWSER_COMPATIBLE:
228 form = new HttpBrowserCompatibleMultipart(charsetCopy, boundaryCopy, bodyPartsCopy);
229 break;
230 case RFC6532:
231 form = new HttpRFC6532Multipart(charsetCopy, boundaryCopy, bodyPartsCopy);
232 break;
233 default:
234 form = new HttpStrictMultipart(charsetCopy, boundaryCopy, bodyPartsCopy);
235 }
236 return new MultipartFormEntity(form, contentTypeCopy, form.getTotalLength());
237 }
238
239 public HttpEntity build() {
240 return buildEntity();
241 }
242
243 }