/// <summary> /// Deserialize the content from the stream. /// </summary> /// <param name="contentType">Used to identify the object which is about to be deserialized. Specified by the <c>Serialize()</c> method when invoked in the other end point.</param> /// <param name="source">Stream that contains the object to deserialize.</param> /// <returns>Created object</returns> /// <exception cref="SerializationException">Deserialization failed</exception> public object Deserialize(string contentType, Stream source) { if (contentType == null) throw new ArgumentNullException("contentType"); if (source == null) throw new ArgumentNullException("source"); if (!contentType.StartsWith(MimeType, StringComparison.OrdinalIgnoreCase)) return null; var result = new FormAndFilesResult() { Form = new ParameterCollection(), Files = new HttpFileCollection() }; var contentTypeHeader = new HttpHeaderValue(contentType); var encodingStr = contentTypeHeader.Parameters["charset"]; var encoding = encodingStr != null ? Encoding.GetEncoding(encodingStr) : Encoding.UTF8; //multipart/form-data, boundary=AaB03x var boundary = contentTypeHeader.Parameters.Get("boundary"); if (boundary == null) throw new DecoderFailureException("Missing boundary in content type: " + contentType); var multipart = new HttpMultipart(source, boundary.Value, encoding); HttpMultipart.Element element; while ((element = multipart.ReadNextElement()) != null) { if (string.IsNullOrEmpty(element.Name)) throw new DecoderFailureException(string.Format("Missing value name.\nElement: {0}", element)); if (!string.IsNullOrEmpty(element.Filename)) { if (string.IsNullOrEmpty(element.ContentType)) throw new DecoderFailureException(string.Format("Value '{0}' lacks a content type.", element.Name)); // Read the file data var buffer = new byte[element.Length]; source.Seek(element.Start, SeekOrigin.Begin); source.Read(buffer, 0, (int)element.Length); // Generate a filename var originalFileName = element.Filename; var internetCache = Environment.GetFolderPath(Environment.SpecialFolder.InternetCache); // if the internet path doesn't exist, assume mono and /var/tmp var path = string.IsNullOrEmpty(internetCache) ? Path.Combine("var", "tmp") : Path.Combine(internetCache.Replace("\\\\", "\\"), "tmp"); element.Filename = Path.Combine(path, Math.Abs(element.Filename.GetHashCode()) + ".tmp"); // If the file exists generate a new filename while (File.Exists(element.Filename)) element.Filename = Path.Combine(path, Math.Abs(element.Filename.GetHashCode() + 1) + ".tmp"); if (!Directory.Exists(path)) Directory.CreateDirectory(path); File.WriteAllBytes(element.Filename, buffer); var file = new HttpFile { Name = element.Name, OriginalFileName = originalFileName, ContentType = element.ContentType, TempFileName = element.Filename }; result.Files.Add(file); } else { var buffer = new byte[element.Length]; source.Seek(element.Start, SeekOrigin.Begin); source.Read(buffer, 0, (int)element.Length); result.Form.Add(Uri.UnescapeDataString(element.Name), encoding.GetString(buffer)); } } return result; }
/// <summary> /// Decode body stream /// </summary> /// <param name="message">Contains the body to decode. Expectes the body to be in format <c>multipart/form-data</c></param> /// <returns> /// <c>true</c> if the body was decoded; otherwise <c>false</c>. /// </returns> /// <exception cref="System.NotSupportedException">MultipartDecoder expects requests of type 'HttpRequest'.</exception> /// <exception cref="DecoderFailureException"> /// Missing boundary in content type: + contentType /// or /// or /// </exception> /// <exception cref="System.FormatException">Missing boundary in content type.</exception> public bool Decode(IHttpRequest message) { if (!message.ContentType.StartsWith(MimeType)) return false; var msg = message as HttpRequest; if (msg == null) throw new NotSupportedException("MultipartDecoder expects requests of type 'HttpRequest'."); var contentType = new HttpHeaderValue(message.Headers["Content-Type"]); //multipart/form-data, boundary=AaB03x var boundry = contentType.Parameters.Get("boundary"); if (boundry == null) throw new DecoderFailureException("Missing boundary in content type: " + contentType); var multipart = new HttpMultipart(message.Body, boundry.Value, message.ContentCharset); var form = msg.Form; /* FileStream stream1 = new FileStream("C:\\temp\\mimebody.tmp", FileMode.Create); byte[] bytes = new byte[stream.Length]; stream.Read(bytes, 0, bytes.Length); stream1.Write(bytes, 0, bytes.Length); stream1.Flush(); stream1.Close(); */ HttpMultipart.Element element; while ((element = multipart.ReadNextElement()) != null) { if (string.IsNullOrEmpty(element.Name)) throw new DecoderFailureException(string.Format("Missing value name.\nElement: {0}", element)); if (!string.IsNullOrEmpty(element.Filename)) { if (string.IsNullOrEmpty(element.ContentType)) throw new DecoderFailureException(string.Format("Value '{0}' lacks a content type.", element.Name)); // Read the file data var buffer = new byte[element.Length]; message.Body.Seek(element.Start, SeekOrigin.Begin); message.Body.Read(buffer, 0, (int) element.Length); // Generate a filename var originalFileName = element.Filename; var internetCache = Environment.GetFolderPath(Environment.SpecialFolder.InternetCache); // if the internet path doesn't exist, assume mono and /var/tmp var path = string.IsNullOrEmpty(internetCache) ? Path.Combine("var", "tmp") : Path.Combine(internetCache.Replace("\\\\", "\\"), "tmp"); element.Filename = Path.Combine(path, Math.Abs(element.Filename.GetHashCode()) + ".tmp"); // If the file exists generate a new filename while (File.Exists(element.Filename)) element.Filename = Path.Combine(path, Math.Abs(element.Filename.GetHashCode() + 1) + ".tmp"); if (!Directory.Exists(path)) Directory.CreateDirectory(path); File.WriteAllBytes(element.Filename, buffer); var file = new HttpFile { Name = element.Name, OriginalFileName = originalFileName, ContentType = element.ContentType, TempFileName = element.Filename }; msg.Files.Add(file); } else { var buffer = new byte[element.Length]; message.Body.Seek(element.Start, SeekOrigin.Begin); message.Body.Read(buffer, 0, (int) element.Length); form.Add(Uri.UnescapeDataString(element.Name), message.ContentCharset.GetString(buffer)); } } return true; }