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.ByteArrayOutputStream;
31 import java.io.IOException;
32 import java.io.OutputStream;
33 import java.nio.ByteBuffer;
34 import java.nio.CharBuffer;
35 import java.nio.charset.Charset;
36 import java.util.List;
37
38 import com.foxinmy.weixin4j.http.apache.content.ContentBody;
39 import com.foxinmy.weixin4j.util.ByteArrayBuffer;
40
41
42
43
44
45
46
47
48 abstract class AbstractMultipartForm {
49
50 private static ByteArrayBuffer encode(
51 final Charset charset, final String string) {
52 final ByteBuffer encoded = charset.encode(CharBuffer.wrap(string));
53 final ByteArrayBuffer bab = new ByteArrayBuffer(encoded.remaining());
54 bab.append(encoded.array(), encoded.position(), encoded.remaining());
55 return bab;
56 }
57
58 private static void writeBytes(
59 final ByteArrayBuffer b, final OutputStream out) throws IOException {
60 out.write(b.buffer(), 0, b.length());
61 }
62
63 private static void writeBytes(
64 final String s, final Charset charset, final OutputStream out) throws IOException {
65 final ByteArrayBuffer b = encode(charset, s);
66 writeBytes(b, out);
67 }
68
69 private static void writeBytes(
70 final String s, final OutputStream out) throws IOException {
71 final ByteArrayBuffer b = encode(MIME.DEFAULT_CHARSET, s);
72 writeBytes(b, out);
73 }
74
75 protected static void writeField(
76 final MinimalField field, final OutputStream out) throws IOException {
77 writeBytes(field.getName(), out);
78 writeBytes(FIELD_SEP, out);
79 writeBytes(field.getBody(), out);
80 writeBytes(CR_LF, out);
81 }
82
83 protected static void writeField(
84 final MinimalField field, final Charset charset, final OutputStream out) throws IOException {
85 writeBytes(field.getName(), charset, out);
86 writeBytes(FIELD_SEP, out);
87 writeBytes(field.getBody(), charset, out);
88 writeBytes(CR_LF, out);
89 }
90
91 private static final ByteArrayBuffer FIELD_SEP = encode(MIME.DEFAULT_CHARSET, ": ");
92 private static final ByteArrayBuffer CR_LF = encode(MIME.DEFAULT_CHARSET, "\r\n");
93 private static final ByteArrayBuffer TWO_DASHES = encode(MIME.DEFAULT_CHARSET, "--");
94
95 final Charset charset;
96 final String boundary;
97
98
99
100
101
102
103
104
105 public AbstractMultipartForm(final Charset charset, final String boundary) {
106 super();
107 this.charset = charset != null ? charset : MIME.DEFAULT_CHARSET;
108 this.boundary = boundary;
109 }
110
111 public AbstractMultipartForm(final String boundary) {
112 this(null, boundary);
113 }
114
115 public abstract List<FormBodyPart> getBodyParts();
116
117 void doWriteTo(
118 final OutputStream out,
119 final boolean writeContent) throws IOException {
120
121 final ByteArrayBuffer boundaryEncoded = encode(this.charset, this.boundary);
122 for (final FormBodyPart part: getBodyParts()) {
123 writeBytes(TWO_DASHES, out);
124 writeBytes(boundaryEncoded, out);
125 writeBytes(CR_LF, out);
126
127 formatMultipartHeader(part, out);
128
129 writeBytes(CR_LF, out);
130
131 if (writeContent) {
132 part.getBody().writeTo(out);
133 }
134 writeBytes(CR_LF, out);
135 }
136 writeBytes(TWO_DASHES, out);
137 writeBytes(boundaryEncoded, out);
138 writeBytes(TWO_DASHES, out);
139 writeBytes(CR_LF, out);
140 }
141
142
143
144
145 protected abstract void formatMultipartHeader(
146 final FormBodyPart part,
147 final OutputStream out) throws IOException;
148
149
150
151
152
153
154 public void writeTo(final OutputStream out) throws IOException {
155 doWriteTo(out, true);
156 }
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172 public long getTotalLength() {
173 long contentLen = 0;
174 for (final FormBodyPart part: getBodyParts()) {
175 final ContentBody body = part.getBody();
176 final long len = body.getContentLength();
177 if (len >= 0) {
178 contentLen += len;
179 } else {
180 return -1;
181 }
182 }
183 final ByteArrayOutputStream out = new ByteArrayOutputStream();
184 try {
185 doWriteTo(out, false);
186 final byte[] extra = out.toByteArray();
187 return contentLen + extra.length;
188 } catch (final IOException ex) {
189
190 return -1;
191 }
192 }
193
194 }