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
29
30 package org.apache.commons.httpclient.methods.multipart;
31
32 import java.io.File;
33 import java.io.FileNotFoundException;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.OutputStream;
37 import org.apache.commons.httpclient.util.EncodingUtil;
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40
41 /***
42 * This class implements a part of a Multipart post object that
43 * consists of a file.
44 *
45 * @author <a href="mailto:mattalbright@yahoo.com">Matthew Albright</a>
46 * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
47 * @author <a href="mailto:adrian@ephox.com">Adrian Sutton</a>
48 * @author <a href="mailto:becke@u.washington.edu">Michael Becke</a>
49 * @author <a href="mailto:mdiggory@latte.harvard.edu">Mark Diggory</a>
50 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
51 * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
52 *
53 * @since 2.0
54 *
55 */
56 public class FilePart extends PartBase {
57
58 /*** Default content encoding of file attachments. */
59 public static final String DEFAULT_CONTENT_TYPE = "application/octet-stream";
60
61 /*** Default charset of file attachments. */
62 public static final String DEFAULT_CHARSET = "ISO-8859-1";
63
64 /*** Default transfer encoding of file attachments. */
65 public static final String DEFAULT_TRANSFER_ENCODING = "binary";
66
67 /*** Log object for this class. */
68 private static final Log LOG = LogFactory.getLog(FilePart.class);
69
70 /*** Attachment's file name */
71 protected static final String FILE_NAME = "; filename=";
72
73 /*** Attachment's file name as a byte array */
74 private static final byte[] FILE_NAME_BYTES =
75 EncodingUtil.getAsciiBytes(FILE_NAME);
76
77 /*** Source of the file part. */
78 private PartSource source;
79
80 /***
81 * FilePart Constructor.
82 *
83 * @param name the name for this part
84 * @param partSource the source for this part
85 * @param contentType the content type for this part, if <code>null</code> the
86 * {@link #DEFAULT_CONTENT_TYPE default} is used
87 * @param charset the charset encoding for this part, if <code>null</code> the
88 * {@link #DEFAULT_CHARSET default} is used
89 */
90 public FilePart(String name, PartSource partSource, String contentType, String charset) {
91
92 super(
93 name,
94 contentType == null ? DEFAULT_CONTENT_TYPE : contentType,
95 charset == null ? "ISO-8859-1" : charset,
96 DEFAULT_TRANSFER_ENCODING
97 );
98
99 if (partSource == null) {
100 throw new IllegalArgumentException("Source may not be null");
101 }
102 this.source = partSource;
103 }
104
105 /***
106 * FilePart Constructor.
107 *
108 * @param name the name for this part
109 * @param partSource the source for this part
110 */
111 public FilePart(String name, PartSource partSource) {
112 this(name, partSource, null, null);
113 }
114
115 /***
116 * FilePart Constructor.
117 *
118 * @param name the name of the file part
119 * @param file the file to post
120 *
121 * @throws FileNotFoundException if the <i>file</i> is not a normal
122 * file or if it is not readable.
123 */
124 public FilePart(String name, File file)
125 throws FileNotFoundException {
126 this(name, new FilePartSource(file), null, null);
127 }
128
129 /***
130 * FilePart Constructor.
131 *
132 * @param name the name of the file part
133 * @param file the file to post
134 * @param contentType the content type for this part, if <code>null</code> the
135 * {@link #DEFAULT_CONTENT_TYPE default} is used
136 * @param charset the charset encoding for this part, if <code>null</code> the
137 * {@link #DEFAULT_CHARSET default} is used
138 *
139 * @throws FileNotFoundException if the <i>file</i> is not a normal
140 * file or if it is not readable.
141 */
142 public FilePart(String name, File file, String contentType, String charset)
143 throws FileNotFoundException {
144 this(name, new FilePartSource(file), contentType, charset);
145 }
146
147 /***
148 * FilePart Constructor.
149 *
150 * @param name the name of the file part
151 * @param fileName the file name
152 * @param file the file to post
153 *
154 * @throws FileNotFoundException if the <i>file</i> is not a normal
155 * file or if it is not readable.
156 */
157 public FilePart(String name, String fileName, File file)
158 throws FileNotFoundException {
159 this(name, new FilePartSource(fileName, file), null, null);
160 }
161
162 /***
163 * FilePart Constructor.
164 *
165 * @param name the name of the file part
166 * @param fileName the file name
167 * @param file the file to post
168 * @param contentType the content type for this part, if <code>null</code> the
169 * {@link #DEFAULT_CONTENT_TYPE default} is used
170 * @param charset the charset encoding for this part, if <code>null</code> the
171 * {@link #DEFAULT_CHARSET default} is used
172 *
173 * @throws FileNotFoundException if the <i>file</i> is not a normal
174 * file or if it is not readable.
175 */
176 public FilePart(String name, String fileName, File file, String contentType, String charset)
177 throws FileNotFoundException {
178 this(name, new FilePartSource(fileName, file), contentType, charset);
179 }
180
181 /***
182 * Write the disposition header to the output stream
183 * @param out The output stream
184 * @throws IOException If an IO problem occurs
185 * @see Part#sendDispositionHeader(OutputStream)
186 */
187 protected void sendDispositionHeader(OutputStream out)
188 throws IOException {
189 LOG.trace("enter sendDispositionHeader(OutputStream out)");
190 super.sendDispositionHeader(out);
191 String filename = this.source.getFileName();
192 if (filename != null) {
193 out.write(FILE_NAME_BYTES);
194 out.write(QUOTE_BYTES);
195 out.write(EncodingUtil.getAsciiBytes(filename));
196 out.write(QUOTE_BYTES);
197 }
198 }
199
200 /***
201 * Write the data in "source" to the specified stream.
202 * @param out The output stream.
203 * @throws IOException if an IO problem occurs.
204 * @see org.apache.commons.httpclient.methods.multipart.Part#sendData(OutputStream)
205 */
206 protected void sendData(OutputStream out) throws IOException {
207 LOG.trace("enter sendData(OutputStream out)");
208 if (lengthOfData() == 0) {
209
210
211
212
213 LOG.debug("No data to send.");
214 return;
215 }
216
217 byte[] tmp = new byte[4096];
218 InputStream instream = source.createInputStream();
219 try {
220 int len;
221 while ((len = instream.read(tmp)) >= 0) {
222 out.write(tmp, 0, len);
223 }
224 } finally {
225
226 instream.close();
227 }
228 }
229
230 /***
231 * Returns the source of the file part.
232 *
233 * @return The source.
234 */
235 protected PartSource getSource() {
236 LOG.trace("enter getSource()");
237 return this.source;
238 }
239
240 /***
241 * Return the length of the data.
242 * @return The length.
243 * @throws IOException if an IO problem occurs
244 * @see org.apache.commons.httpclient.methods.multipart.Part#lengthOfData()
245 */
246 protected long lengthOfData() throws IOException {
247 LOG.trace("enter lengthOfData()");
248 return source.getLength();
249 }
250
251 }