Ejemplo n.º 1
0
        /// <summary>
        /// Get form collection with values from query
        /// </summary>
        /// <returns></returns>
        public FormCollection GetFormCollection()
        {
            if (HttpContext.Request.Method == HTTPMethod.Get)
            {
                return new FormCollection(HttpContext.Request.Uri.QueryString);
            }
            else if (HttpContext.Request.Method == HTTPMethod.Post)
            {
                var socket = HttpContext.Socket;
                var buffer = new byte[2048];

                var formCollection = new FormCollection(HttpContext.Request.Uri.QueryString);

                while (socket.Available > 0)
                {
                    socket.ReceiveUntil(buffer, "&");
                    var keyValuePair = new String(Encoding.UTF8.GetChars(buffer)).Split('=');
                    formCollection.AddValue(keyValuePair[0], keyValuePair[1]);
                }

                return formCollection;
            }

            throw new NotSupportedException("Only GET and POST is supported");
        }
        //private const int _PostRxBufferSize = 1500;
        public FormCollection RecieveFiles()
        {
            var request = HttpContext.Request;

            if (request.Method == HTTPMethod.Post &&
                request.ContentType.MainContentType == EnumMainContentType.MultiPart &&
                request.ContentType.SubContentType == EnumSubContentType.FormData)
            {
                var contentLengthFromHeader = int.Parse(request.Headers["Content-Length"].ToString());
                var contentLengthReceived = 0;
                var PostedData = new FormCollection();
                var socket = HttpContext.Socket;
                var allDataRecieved = false;
                var receivedByteCount = 0;
                var buffer = new byte[2048]; //The size of this array essentially sets the read rate...
                var fileDirectoryPath = SDCardManager.GetWorkingDirectoryPath();
                var boundaryBytes = Encoding.UTF8.GetBytes(request.Boundary);
                var BeginningboundaryBytes = Encoding.UTF8.GetBytes("\r\n-----");
                var strBldrBoundaryHeader = new StringBuilder();
                var strBldrBoundaryData = new StringBuilder();
                StringBuilder strBldr = new StringBuilder();
                var BoundaryDataSeparator = Encoding.UTF8.GetBytes("\r\n\r\n"); //a double newline delimits Boundary Headers from Boundary Data...
                var BoundaryDataIndex = 0;
                Regex rx = new Regex("([^=\\s]+)=\"([^\"]*)\""); //matches key value pairs like the below...
                //var Value = "key1=\"value1\" key2=\"value 2\" key3=\"value3\" key4=\"value4\" key5=\"5555\" key6=\"xxx666\"";

                Debug.Print("Boundary is: " + request.Boundary); //The Boundary property will be populated if it is multipart/form-data
                Debug.Print("Reading Bytes...");
                socket.ReceiveUntil(buffer, boundaryBytes, out receivedByteCount, true); //Discard the first Boundary Read...

                while (!allDataRecieved)
                {
                    contentLengthReceived += receivedByteCount;
                    Debug.Print("Bytes Read: " + receivedByteCount +
                    "\r\nTotal Bytes Read: " + contentLengthReceived +
                    "\r\nTotal Bytes To Read: " + contentLengthFromHeader);

                    if (contentLengthReceived < contentLengthFromHeader)
                    {
                        Debug.Print("Reading Bytes...");
                        socket.ReceiveUntil(buffer, boundaryBytes, out receivedByteCount, true);
                        BoundaryDataIndex = buffer.IndexOf(BoundaryDataSeparator);
                        //Debug.Print("Boundary Data Index: " + BoundaryDataIndex);

                        /*The end of the  multipart form is denoted by the boundary data followed by -- and a Carriage Return Line Feed (ex -----------------------------42291685921978--)
                         * Since I read until the the Boundary Data, I loop until only those characters are found; I do a check for null bytes just to make sure.*/
                        if (buffer.IndexOf(Encoding.UTF8.GetBytes("--\r\n")) == 0 && buffer[5] == default(byte))
                        {
                            Debug.Print("You've reached the end of the multipart form! ");
                            continue;
                        }

                        strBldrBoundaryHeader.Clear();
                        strBldrBoundaryHeader.Append(Encoding.UTF8.GetChars(buffer.SubArray(0, BoundaryDataIndex + 1)));
                        //Debug.Print("Boundary Header: \r\n" + strBldrBoundaryHeader.ToString().ToString().Trim());

                        var objBoundaryHeaderCollection = new BoundaryHeaderCollection(strBldrBoundaryHeader.ToString());

                        strBldr.Clear();
                        strBldr.Append(objBoundaryHeaderCollection["Content-Disposition".ToLower()]); //I store all keys in lowercase...
                        //Debug.Print("Content-Disposition Value: " + strBldr);
                        var KeyValuePairs = new Hashtable();
                        foreach (Match m in rx.Matches(strBldr.ToString()))
                        {
                            Debug.Print("Found KeyValue Pair:" +
                                "\r\n\tKey: " + m.Groups[1] +
                                "\r\n\tValue: " + m.Groups[2]);
                            KeyValuePairs.Add(m.Groups[1].ToString().ToLower(), m.Groups[2]);

                        }

                        if (objBoundaryHeaderCollection.Contains("Content-Type".ToLower()))//write Boundary Data to File...
                        {
                            strBldr.Clear();//Get the value portion of the Content-Type Boundary Header
                            strBldr.Append(objBoundaryHeaderCollection["Content-Type".ToLower()]); //I store all keys in lowercase...
                            Debug.Print("I've got a file and the Content-Type is: " + strBldr.ToString());

                            //Get the file's name from the KeyValuePairs...
                            string fileName = string.Empty;
                            if (KeyValuePairs.Contains("filename")) //JQuery ajax post (from <input type="file">) sends filename parameter containing file's name; the name property is left as defined in the html.
                                fileName = KeyValuePairs["filename"].ToString();
                            else if (KeyValuePairs.Contains("name")) //Form Post sends name parameter containing file's name (no filename parameter is sent)
                                fileName = KeyValuePairs["name"].ToString();
                            else
                                fileName = "Unknown.txt";
                            Debug.Print("File name is set to: " + fileName);

                            if (buffer.IndexOf(boundaryBytes) == -1) //Write to file, loop to get remaining file data
                            {
                                var BoundaryData = buffer.SubArray(BoundaryDataIndex + BoundaryDataSeparator.Length, receivedByteCount - BoundaryDataIndex - BoundaryDataSeparator.Length);
                                var intTemp = receivedByteCount;
                                SDCardManager.Write(fileDirectoryPath, fileName, System.IO.FileMode.Create, BoundaryData, BoundaryData.Length);
                                while (buffer.IndexOf(boundaryBytes) == -1)  //boundary hasn't been reached, get more data...
                                {
                                    Debug.Print("Getting more File data...");
                                    socket.ReceiveUntil(buffer, boundaryBytes, out receivedByteCount, true);
                                    if (buffer.IndexOf(boundaryBytes) != -1)//remove boundary string here before you have written to a file...
                                    {
                                        var intBeginningBoundaryBytesIndex = buffer.IndexOf(BeginningboundaryBytes);
                                        var Data = buffer.SubArray(0, intBeginningBoundaryBytesIndex);
                                        SDCardManager.Write(fileDirectoryPath, fileName, System.IO.FileMode.Append, Data, Data.Length);
                                    }
                                    else
                                        SDCardManager.Write(fileDirectoryPath, fileName, System.IO.FileMode.Append, buffer, receivedByteCount);
                                    intTemp += receivedByteCount;
                                    Debug.Print("Iterated a loop and Recieved: " + receivedByteCount + " Bytes...");
                                }

                                receivedByteCount = intTemp;
                            }
                            else //remove boundary string, write to file and exit...
                            {
                                var BoundaryData = buffer.SubArray(BoundaryDataIndex + BoundaryDataSeparator.Length, receivedByteCount - BoundaryDataIndex - BoundaryDataSeparator.Length + 1);
                                var intBeginningBoundaryBytesIndex = BoundaryData.IndexOf(BeginningboundaryBytes);
                                var Data = BoundaryData.SubArray(0, intBeginningBoundaryBytesIndex);
                                SDCardManager.Write(fileDirectoryPath, fileName, System.IO.FileMode.Append, Data, Data.Length);
                            }
                        }
                        else //add the 'name' value and BoundaryData to the PostedData FormCollection object...
                        {
                            strBldrBoundaryData.Clear();
                            strBldrBoundaryData.Append(Encoding.UTF8.GetChars(buffer.SubArray(BoundaryDataIndex + BoundaryDataSeparator.Length, buffer.Length - BoundaryDataIndex - BoundaryDataSeparator.Length)));
                            //Debug.Print("Boundary Data: \r\n" + strBldrBoundaryData.ToString());

                            var strBoundaryData = strBldrBoundaryData.ToString();
                            if (KeyValuePairs.Contains("name"))
                                PostedData.AddValue(KeyValuePairs["name"].ToString(), strBoundaryData.Substring(0, strBoundaryData.IndexOf('\n')));
                            Debug.Print("Added Key/Value Pair to PostedData FormCollection...");
                        }

                        //var data = socket.GetMoreBytes(2048, out receivedByteCount);
                        //SDCardManager.Write(fileDirectoryPath, "Test.txt", System.IO.FileMode.Append, data, receivedByteCount);

                    }
                    else
                        allDataRecieved = true;
                }

                return PostedData;
            }

            throw new NotSupportedException("Only POST is supported");
        }