Due to the 300 line limit for postings, I had to separate my posts.
Combine the following code with Part 3: file upload Java/HTML code.
*---------------------*
//---------------------------------------------------------------------------
// The meat of the servlet. This method parses the input, and
// returns a hashtable of either String[] values (for parameters)
// or Hashtable values (for files uploaded). The values of the entries
// in the hashtable are name, filename, Content-Type, and Contents.
// Note that uploads should be capped in size by the calling method, since
// otherwise a denial of service attack on server memory becomes trivial.
//---------------------------------------------------------------------------
Hashtable parseMulti(String boundary, ServletInputStream in) throws
IOException
{
int buffSize = 1024 * 8; // 8K
Hashtable hash = new Hashtable();
int result;
String line, lowerline, filename, contentType, name, value;
String boundaryStr = "--" + boundary;
ByteArrayOutputStream content;
byte[] b = new byte[buffSize];
result = in.readLine(b, 0, b.length);
// failure.
if (result == -1)
throw new IllegalArgumentException("InputStream truncated");
line = new String(b, 0, 0, result);
// failure.
if (!line.startsWith(boundaryStr))
throw new IllegalArgumentException("MIME boundary missing: " + line);
while (true) {
// Some initialization
name = filename = contentType = null;
content = new ByteArrayOutputStream();
// get next line (should be content disposition)
result = in.readLine(b, 0, b.length);
if (result == -1)
return hash;
line = new String(b, 0, 0, result - 2);
lowerline = line.toLowerCase();
if (!lowerline.startsWith("content-disposition"))
// don't know what to do, so we'll keep looking...
continue;
// determine what the disposition is
int ind = lowerline.indexOf("content-disposition: ");
int ind2 = lowerline.indexOf(";");
if (ind == -1 || ind2 == -1)
throw new IllegalArgumentException("Content Disposition line " +
"misformatted: " + line);
String disposition = lowerline.substring(ind + 21, ind2);
if (!disposition.equals("form-data"))
throw new IllegalArgumentException("Content Disposition of " +
disposition + " is not
supported");
// determine what the name is
int ind3 = lowerline.indexOf("name=\"", ind2);
int ind4 = lowerline.indexOf("\"", ind3 + 7);
if (ind3 == -1 || ind4 == -1)
throw new IllegalArgumentException("Content Disposition line " +
"misformatted: " + line);
name = line.substring(ind3 + 6, ind4);
// determine filename, if any
int ind5 = lowerline.indexOf("filename=\"", ind4 + 2);
int ind6 = lowerline.indexOf("\"", ind5 + 10);
if (ind5 != -1 && ind6 != -1) {
filename = line.substring(ind5 + 10, ind6);
}
// Whew! We now move onto the next line, which
// will either be blank, or Content-Type, followed by blank.
result = in.readLine(b, 0, b.length);
if (result == -1)
return hash;
line = new String(b, 0, 0, result - 2); // -2 to remove \r\n
lowerline = line.toLowerCase();
if (lowerline.startsWith("content-type")) {
int ind7 = lowerline.indexOf(" ");
if (ind7 == -1)
throw new IllegalArgumentException("Content-Type line " +
"misformatted: " + line);
contentType = lowerline.substring(ind7 + 1);
// read blank header line
result = in.readLine(b, 0, b.length);
if (result == -1)
return hash;
line = new String(b, 0, 0, result - 2); // -2 to remove \r\n
if (line.length() != 0) {
throw new IllegalArgumentException("Unexpected line in " +
"MIMEpart header: " + line);
}
}
else if (line.length() != 0) {
throw new IllegalArgumentException("Misformatted line " +
"following disposition: " +
line);
}
//read content, implement readahead by one line
boolean readingContent = true;
boolean firstLine = true;
byte[] buffbytes = new byte[buffSize];
int buffnum = 0;
result = in.readLine(b, 0, b.length);
if (result == -1)
return hash;
line = new String(b, 0, 0, result);
if (!line.startsWith(boundaryStr)) {
System.arraycopy(b, 0, buffbytes, 0, result);
buffnum = result;
result = in.readLine(b, 0, b.length);
if (result == -1)
return hash;
line = new String(b, 0, 0, result);
firstLine = false;
if (line.startsWith(boundaryStr)) {
readingContent = false;
}
}
else {
readingContent = false;
}
while (readingContent) {
content.write(buffbytes, 0, buffnum);
System.arraycopy(b, 0, buffbytes, 0, result);
buffnum = result;
result = in.readLine(b, 0, b.length);
if (result == -1)
return hash;
line = new String(b, 0, 0, result);
if (line.startsWith(boundaryStr))
readingContent = false;
}
if (!firstLine) {
// -2 to trim \r\n
if (buffnum > 2)
content.write(buffbytes, 0, buffnum - 2);
}
//now set appropriate variable, populate hashtable
if (filename == null) {
if (hash.get(name) == null) {
String[] values = new String[1];
values[0] = content.toString();
hash.put(name, values);
}
else {
Object prevobj = hash.get(name);
if (prevobj instanceof String[]) {
String[] prev = (String[])prevobj;
String[] newStr = new String[prev.length + 1];
System.arraycopy(prev, 0, newStr, 0, prev.length);
newStr[prev.length] = content.toString();
hash.put(name, newStr);
}
else {
//now what? I think this breaks the standard.
throw new IllegalArgumentException("failure in parseMulti " +
"hashtable building code");
}
}
}
else {
// Yes, we don't return Hashtable[] for multiple
// files of same name. AFAIK, that's not allowed.
Hashtable filehash = new Hashtable(4);
filehash.put("name", name);
filehash.put("filename", filename);
if (contentType == null)
contentType = "application/octet-stream";
filehash.put("content-type", contentType);
filehash.put("content", content.toByteArray());
hash.put(name, filehash);
}
}
}
private void sendFailure(HttpServletResponse response, String reason) throws
IOException
{
ServletOutputStream out = response.getOutputStream();
out.println("<html>");
out.println("<head>");
out.println(" Upload Failure");
out.println("</head>");
out.println("<body>");
out.println("<h2>The upload failed, due to:</h2>");
out.println(reason);
out.println("<br>");
out.println("You may wish to inform the system administrator.");
out.println("</body>");
out.println("</html>");
}
}
___________________________________________________________________________
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff SERVLET-INTEREST".
Archives: http://archives.java.sun.com/archives/servlet-interest.html
Resources: http://java.sun.com/products/servlet/external-resources.html
LISTSERV Help: http://www.lsoft.com/manuals/user/user.html