How do I get my HTTP request handler to accept file uploads?

Hello,
I have written a small HTTP server in Java, its for me to toy around with and use as a basis for other projects. I am having some issues now with receiving HTTP uploads. Initially I had left this ability out of the spec of my http server, but it appears now I need the functionality, so I have gone back and recoded my request object to support it, but whenever I use it (in an upload scenario - everything else works fine) I get a connection reset error.
            I was hoping someone could tell me how to fix my code so that it works properly. Here's what its supposed to do: first it reads all the http header information passed, and stores it in a hashtable for easy reference. After the header is collected if it is a post command, it collects the additional data and stores it in the hashtable as well, finally, if it finds the content type to be multi-part form data, it reads in the remaining bytes, and should process them into another hashtable stored value (for later processing, or writing to disk).

A working fix to this is worth 500 points. The function in question is called processRequest.

Thanks,
Rick


Here is the code:

/*
 * Request.java
 *
 * Created on January 13, 2007, 1:25 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */


import java.util.*;
import java.io.*;
import java.net.*;

/**
 *
 * @author Rick
 */
public class Request
{    
    /** Creates a new instance of Request */
    Socket client;
    Hashtable requestHeaders;
    config cfg;
    int errorLevel = 0;
   
    public Request(Socket client, config cfg)
    {
        this.client = client;
        this.cfg = cfg;
        requestHeaders = new Hashtable();
    }
   
    public boolean requestValueExists(String value)
    {
        return (requestHeaders.get(value) != null);
    }
   
    public void processRequest()
    {
        //grabs the whole header and sets the request hashtable up
        try
        {
            //get the request
            BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream(),"8859_1"));
            String req_in = "";
            int line = 0;
            requestHeaders.put("local_ip",client.getLocalAddress().getHostAddress());
           
            while ((req_in=in.readLine()).length() > 0)
            {
                //System.out.println(req_in);
                if (line == 0)
                {
                    //it is the page requested break it apart into query string, requested page, request type, and protocol, also set the requesting ip, and hostname
                   String reqs[] = req_in.split(" ");
                   
                   //set up the request type
                   requestHeaders.put("request_method",reqs[0].replace('/',' ').trim());
                   
                   //first split the requested file by ?
                   String tw[] = reqs[1].split("\\?");
                   
                   requestHeaders.put("page_requested",tw[0]);
                     
                   if (tw.length == 2)
                        requestHeaders.put("query_string",tw[1]);
                   
                   //set up the protocol
                   requestHeaders.put("remote_protocol",reqs[2]);
       
                   //get the hostname and ip of the requester
                   String hostnameIP = client.getInetAddress().toString();      
                   String clientInfo[] = hostnameIP.split("/");
           
                   //set up the remote hostname
                   requestHeaders.put("remote_hostname",clientInfo[0]);
                   
                   //set up the remote ip
                   requestHeaders.put("remote_ip",clientInfo[0]);  
                   
                   line=1;
                }
                else
                {
                    //split the string by :
                    String reqs[] = req_in.split(":");
                   
                    if (reqs.length == 2)
                        requestHeaders.put(reqs[0].toLowerCase().trim(),reqs[1].trim());
                    else
                        requestHeaders.put(reqs[0].toLowerCase().trim(),reqs[1].trim() + ":" + reqs[2].trim());
                }
            }   /* end of get request headers */
           
            //now check to see if there is any POST data to collect
            if ((requestHeaders.get("request_method").toString().compareTo("POST") == 0) && (requestHeaders.containsKey("content-length")) && (requestHeaders.containsKey("content-type")))
            {
                //it is a post method and there is data to collect so collect it
                //first get the total content length
                int contentLength = new Integer(requestHeaders.get("content-length").toString()).intValue();
               
                char[] postdata = new char[contentLength];
               
                //read in til the length is hit
                in.read(postdata,0,contentLength);
               
                String post_data = new String(postdata);
               
                //determine if it is a normal form submit or a multi-part form submit
                if (requestHeaders.get("content-type").toString().indexOf("multipart/form-data; boundary=") > -1)
                {
                    //get the data boundary
                    String boundary = "--" + requestHeaders.get("content-type").toString().replaceAll("multipart/form-data; boundary=","");
                   
                    //split the post_data apart by the boundary leaving data parts + 1
                    String formdata[] = post_data.split(boundary);
                   
                    System.out.println("Data Parts: " + formdata.length);
                    System.out.println("------------------");
                   
                    //process each of the data parts
                    for (int i=0; i < formdata.length; i++)
                    {
                        //System.out.println("DataPart " + i);
                       
                        //first find the Content-Disposition
                        int start = formdata[i].toLowerCase().indexOf("content-disposition: form-data; name=");
                        int end = formdata[i].toLowerCase().indexOf("\r\n",start+1);
                       
                        //System.out.println("Start:" + start);
                        //System.out.println("End:" + end);
                       
                        if ((start > -1) && (start < end))
                        {
                            String disposition = formdata[i].substring(start,end);
                       
                            //now determine if the disposution type is formdata or a file upload
                            if (disposition.toLowerCase().indexOf("filename") > -1)
                            {
                                //it is a file upload so lets start by collecting the variable name and value
                               
                                //first split the disposition by ;
                                String uploaddata[] = disposition.split(";");
                               
                                String key = uploaddata[1].toLowerCase().replaceAll("name=","").replaceAll("\"","");
                                String value = uploaddata[2].toLowerCase().replaceAll("filename=","").replaceAll("\"","");
                               
                                requestHeaders.put(key.trim(),value.trim());
                               
                                //ok lets pull the disposition line out of the data
                                String data = formdata[i].replaceAll(disposition,"");
                               
                                //ok now we have to grab the content type of the file
                                start = formdata[i].toLowerCase().indexOf("content-type");
                                end = formdata[i].toLowerCase().indexOf("\r\n",start);
                               
                                String content_type = formdata[i].substring(start,end);
                               
                                requestHeaders.put("file-content-type",content_type.split(":")[1].trim());
                               
                                //remove the content_type
                                System.out.println(data.replaceAll(content_type,"").trim().getBytes().length);
                                requestHeaders.put(value.trim(),data.replaceAll(content_type,"").trim().getBytes());                                
                            }
                            else
                            {
                                if (disposition.split("=")[1].length() > 0)
                                //it is a normal data variable so get the key / value pair and insert it into the request hash
                                requestHeaders.put(disposition.split("=")[1].replaceAll("\"",""),formdata[i].replaceAll(disposition,"").replaceAll("\r\n",""));
                            }
                        }
                        //System.out.println("--------------------");
                    }
                }
                else
                {
               
                    //convert it to a string
                    String pdata[] = post_data.split("&");
               
                    //loop over the results and split by the = sign
                    for (int i = 0; i < pdata.length; i++)
                    {
                        String data[] = pdata[i].split("=");
                        if(data.length == 2)
                            requestHeaders.put(data[0],URLDecoder.decode(data[1]));
                        else
                            requestHeaders.put(data[0],"");
                    }
                }
            }    
        }
        catch(Exception e)
        {
            cfg.writeLog("HTTP Request: Client Connection Error. (" + e.toString() + ").");
            e.printStackTrace();
            errorLevel = 1;
        }
    } // end of processRequest()
   
    public Enumeration getKeyList()
    {
        //return an enumeration of all the key values in the requestHeader hash
        return requestHeaders.keys();
    }
   
    public String getRequestValue(String value)
    {
        //return the requested value from the requestHeader hash
        return requestHeaders.get(value).toString();
    }
   
   
}
richardsimnettAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

ksivananthCommented:
can you post the exception stack too?
0
richardsimnettAuthor Commented:
It doesnt throw an exception at all. Instead the browser simply stops, and displays a message connection reset. It only does this on files larger than 1k, and that are binary. Small text files (<1k) go through fine.

Thanks,
Rick
0
objectsCommented:
u can't use a Reader to read binary data, need to use an InputStream
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

richardsimnettAuthor Commented:
objects,
is it possible to use a combination of BufferedReader and InputStream? Basically use a buffered reader to read the HTTP header, and then an InputStream to read in the post data?

Thanks,
Rick
0
richardsimnettAuthor Commented:
nevermind that last question. I proved it cant be done. Im re-coding the entire thing to use inputstream. I will post my results.

Thanks,
Rick
0
richardsimnettAuthor Commented:
Objects,
Got it works well with InputStream.

Thanks!
Rick
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.