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