001: /*
002: * $Id: HttpRequestFileUpload.java,v 1.1 2003/08/24 09:33:33 jonesde Exp $
003: *
004: * Copyright (c) 2001 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: */
024:
025: package org.ofbiz.base.util;
026:
027: import java.io.FileOutputStream;
028: import java.io.IOException;
029: import java.util.Date;
030: import java.util.Dictionary;
031: import java.util.Hashtable;
032:
033: import javax.servlet.ServletInputStream;
034: import javax.servlet.http.HttpServletRequest;
035:
036: /**
037: * HttpRequestFileUpload - Receive a file upload through an HttpServletRequest
038: *
039: * @author Dustin Caldwell
040: * @version 1.0
041: */
042: public class HttpRequestFileUpload {
043:
044: private int BUFFER_SIZE = 4096;
045: private int WAIT_INTERVAL = 200; // in milliseconds
046: private int MAX_WAITS = 20;
047: private int waitCount = 0;
048: private String savePath;
049: private String filepath;
050: private String filename;
051: private String contentType;
052: private String overrideFilename = null;
053: private Dictionary fields;
054:
055: public String getOverrideFilename() {
056: return overrideFilename;
057: }
058:
059: public void setOverrideFilename(String ofName) {
060: overrideFilename = ofName;
061: }
062:
063: public String getFilename() {
064: return filename;
065: }
066:
067: public String getFilepath() {
068: return filepath;
069: }
070:
071: public void setSavePath(String savePath) {
072: this .savePath = savePath;
073: }
074:
075: public String getContentType() {
076: return contentType;
077: }
078:
079: public String getFieldValue(String fieldName) {
080: if (fields == null || fieldName == null)
081: return null;
082: return (String) fields.get(fieldName);
083: }
084:
085: private void setFilename(String s) {
086: if (s == null)
087: return;
088:
089: int pos = s.indexOf("filename=\"");
090:
091: if (pos != -1) {
092: filepath = s.substring(pos + 10, s.length() - 1);
093: // Windows browsers include the full path on the client
094: // But Linux/Unix and Mac browsers only send the filename
095: // test if this is from a Windows browser
096: pos = filepath.lastIndexOf("\\");
097: if (pos != -1)
098: filename = filepath.substring(pos + 1);
099: else
100: filename = filepath;
101: }
102: }
103:
104: private void setContentType(String s) {
105: if (s == null)
106: return;
107:
108: int pos = s.indexOf(": ");
109:
110: if (pos != -1)
111: contentType = s.substring(pos + 2, s.length());
112: }
113:
114: public void doUpload(HttpServletRequest request) throws IOException {
115: ServletInputStream in = request.getInputStream();
116:
117: /* System.out.println("Header:");
118: Enumeration ee = request.getHeaderNames();
119: while(ee.hasMoreElements()) {
120: String ss = (String)ee.nextElement();
121: System.out.println(ss + " = [" + request.getHeader(ss) + "]");
122: }*/
123: String reqLengthString = request.getHeader("content-length");
124:
125: System.out.println("expect " + reqLengthString + " bytes.");
126: int requestLength = 0;
127:
128: try {
129: requestLength = new Integer(reqLengthString).intValue();
130: } catch (Exception e2) {
131: e2.printStackTrace();
132: return;
133: }
134: byte[] line = new byte[BUFFER_SIZE];
135:
136: int i = -1;
137:
138: i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
139: requestLength -= i;
140: if (i < 3)
141: return;
142: int boundaryLength = i - 2;
143:
144: String boundary = new String(line, 0, boundaryLength); // -2 discards the newline character
145:
146: System.out.println("boundary=[" + boundary + "] length is "
147: + boundaryLength);
148: fields = new Hashtable();
149:
150: while (requestLength > 0/* i != -1*/) {
151: String newLine = "";
152:
153: if (i > -1)
154: newLine = new String(line, 0, i);
155: if (newLine
156: .startsWith("Content-Disposition: form-data; name=\"")) {
157: if (newLine.indexOf("filename=\"") != -1) {
158: setFilename(new String(line, 0, i - 2));
159: if (filename == null)
160: return;
161: // this is the file content
162: i = waitingReadLine(in, line, 0, BUFFER_SIZE,
163: requestLength);
164: requestLength -= i;
165:
166: setContentType(new String(line, 0, i - 2));
167:
168: // blank line
169: i = waitingReadLine(in, line, 0, BUFFER_SIZE,
170: requestLength);
171: requestLength -= i;
172: newLine = new String(line, 0, i);
173: String filenameToUse = filename;
174:
175: if (overrideFilename != null) {
176: filenameToUse = overrideFilename;
177: }
178:
179: // first line of actual file
180: i = waitingReadLine(in, line, 0, BUFFER_SIZE,
181: requestLength);
182: requestLength -= i;
183: newLine = new String(line, 0, i);
184:
185: byte[] lastTwoBytes = new byte[2];
186:
187: if (i > 1) {
188: lastTwoBytes[0] = line[i - 2];
189: lastTwoBytes[1] = line[i - 1];
190: }
191: System.out.println("about to create a file:"
192: + (savePath == null ? "" : savePath)
193: + filenameToUse);
194: FileOutputStream fos = new FileOutputStream(
195: (savePath == null ? "" : savePath)
196: + filenameToUse);
197: boolean bail = (new String(line, 0, i)
198: .startsWith(boundary));
199: boolean oneByteLine = (i == 1); // handle one-byte lines
200:
201: while ((requestLength > 0/* i != -1*/) && !bail) {
202:
203: // write the current buffer, except the last 2 bytes;
204: if (i > 1) {
205: fos.write(line, 0, i - 2);
206: }
207:
208: oneByteLine = (i == 1); // we need to track on-byte lines differently
209:
210: i = waitingReadLine(in, line, 0, BUFFER_SIZE,
211: requestLength);
212: requestLength -= i;
213:
214: // the problem is the last line of the file content
215: // contains the new line character.
216:
217: // if the line just read was the last line, we're done.
218: // if not, we must write the last 2 bytes of the previous buffer
219: // just assume that a one-byte line isn't the last line
220:
221: if (requestLength < 1) {
222: bail = true;
223: } else if (oneByteLine) {
224: fos.write(lastTwoBytes, 0, 1); // we only saved one byte
225: } else {
226: fos.write(lastTwoBytes, 0, 2);
227: }
228:
229: if (i > 1) {
230: // save the last 2 bytes of the buffer
231: lastTwoBytes[0] = line[i - 2];
232: lastTwoBytes[1] = line[i - 1];
233: } else {
234: lastTwoBytes[0] = line[0]; // only save one byte
235: }
236: }
237: fos.flush();
238: fos.close();
239: } else {
240: // this is a field
241: // get the field name
242: int pos = newLine.indexOf("name=\"");
243: String fieldName = newLine.substring(pos + 6,
244: newLine.length() - 3);
245:
246: // System.out.println("fieldName:" + fieldName);
247: // blank line
248: i = waitingReadLine(in, line, 0, BUFFER_SIZE,
249: requestLength);
250: requestLength -= i;
251: i = waitingReadLine(in, line, 0, BUFFER_SIZE,
252: requestLength);
253: requestLength -= i;
254: newLine = new String(line, 0, i);
255: StringBuffer fieldValue = new StringBuffer(
256: BUFFER_SIZE);
257:
258: while (requestLength > 0/* i != -1*/
259: && !newLine.startsWith(boundary)) {
260: // The last line of the field
261: // contains the new line character.
262: // So, we need to check if the current line is
263: // the last line.
264: i = waitingReadLine(in, line, 0, BUFFER_SIZE,
265: requestLength);
266: requestLength -= i;
267: if ((i == boundaryLength + 2 || i == boundaryLength + 4) // + 4 is eof
268: && (new String(line, 0, i)
269: .startsWith(boundary)))
270: fieldValue.append(newLine.substring(0,
271: newLine.length() - 2));
272: else
273: fieldValue.append(newLine);
274: newLine = new String(line, 0, i);
275: }
276: // System.out.println("fieldValue:" + fieldValue.toString());
277: fields.put(fieldName, fieldValue.toString());
278: }
279: }
280: i = waitingReadLine(in, line, 0, BUFFER_SIZE, requestLength);
281: if (i > -1)
282: requestLength -= i;
283:
284: } // end while
285: }
286:
287: // reads a line, waiting if there is nothing available and reqLen > 0
288: private int waitingReadLine(ServletInputStream in, byte[] buf,
289: int off, int len, int reqLen) throws IOException {
290: int i = -1;
291:
292: while (((i = in.readLine(buf, off, len)) == -1) && (reqLen > 0)) {
293: System.out.print("waiting");
294: if (waitCount > MAX_WAITS) {
295: System.out.println("waited " + waitCount
296: + " times, bailing out while still expecting "
297: + reqLen + " bytes.");
298: throw new IOException("waited " + waitCount
299: + " times, bailing out while still expecting "
300: + reqLen + " bytes.");
301: }
302: waitCount++;
303: long endMS = new Date().getTime() + WAIT_INTERVAL;
304:
305: while (endMS > (new Date().getTime())) {
306: try {
307: wait(WAIT_INTERVAL);
308: } catch (Exception e3) {
309: System.out.print(".");
310: }
311: }
312: System.out.println((new Date().getTime() - endMS) + " ms");
313: }
314: return i;
315: }
316: }
|