LCOV - code coverage report
Current view: top level - Cqrs.WebApi/Formatters/FormMultipart/Converters - HttpContentToFormDataConverter.cs Hit Total Coverage
Test: doc-coverage.info Lines: 0 3 0.0 %
Date: 2017-07-26

          Line data    Source code
       1             : using System;
       2             : using System.IO;
       3             : using System.Linq;
       4             : using System.Net.Http;
       5             : using System.Net.Http.Headers;
       6             : using System.Threading;
       7             : using System.Threading.Tasks;
       8             : using Cqrs.WebApi.Formatters.FormMultipart.Infrastructure;
       9             : 
      10             : namespace Cqrs.WebApi.Formatters.FormMultipart.Converters
      11             : {
      12             :         public class HttpContentToFormDataConverter
      13           0 :         {
      14           0 :                 public async Task<FormData> Convert(HttpContent content)
      15             :                 {
      16             :                         if(content == null)
      17             :                                 throw new ArgumentNullException("content");
      18             : 
      19             :                         //commented to provide more details about incorrectly formatted data from ReadAsMultipartAsync method
      20             :                         /*if (!content.IsMimeMultipartContent())
      21             :                         {
      22             :                                 throw new Exception("Unsupported Media Type");
      23             :                         }*/
      24             : 
      25             :                         //http://stackoverflow.com/questions/15201255/request-content-readasmultipartasync-never-returns
      26             :                         MultipartMemoryStreamProvider multipartProvider = null;
      27             : 
      28             :                         await Task.Factory
      29             :                                 .StartNewSafely(() =>
      30             :                                         {
      31             :                                                 try
      32             :                                                 {
      33             :                                                         multipartProvider = content.ReadAsMultipartAsync().Result;
      34             :                                                 }
      35             :                                                 catch (AggregateException aggregateException)
      36             :                                                 {
      37             :                                                         if (aggregateException.InnerExceptions.Count != 1)
      38             :                                                                 throw;
      39             :                                                         var exception = aggregateException.InnerExceptions.Single() as IOException;
      40             :                                                         if (exception == null || exception.Message != @"Unexpected end of MIME multipart stream. MIME multipart message is not complete.")
      41             :                                                                 throw;
      42             : 
      43             :                                                         Stream reqStream = content.ReadAsStreamAsync().Result;
      44             :                                                         MemoryStream tempStream = new MemoryStream();
      45             :                                                         reqStream.CopyTo(tempStream);
      46             : 
      47             :                                                         tempStream.Seek(0, SeekOrigin.End);
      48             :                                                         StreamWriter writer = new StreamWriter(tempStream);
      49             :                                                         writer.WriteLine();
      50             :                                                         writer.Flush();
      51             :                                                         tempStream.Position = 0;
      52             : 
      53             : 
      54             :                                                         StreamContent streamContent = new StreamContent(tempStream);
      55             :                                                         foreach (var header in content.Headers)
      56             :                                                                 streamContent.Headers.Add(header.Key, header.Value);
      57             : 
      58             :                                                         // Read the form data and return an async task.
      59             :                                                         multipartProvider = streamContent.ReadAsMultipartAsync().Result;
      60             :                                                 }
      61             :                                         },
      62             :                                         CancellationToken.None,
      63             :                                         TaskCreationOptions.LongRunning, // guarantees separate thread
      64             :                                         TaskScheduler.Default);
      65             : 
      66             :                         var multipartFormData = await Convert(multipartProvider);
      67             :                         return multipartFormData;
      68             :                 }
      69             : 
      70           0 :                 public async Task<FormData> Convert(MultipartMemoryStreamProvider multipartProvider)
      71             :                 {
      72             :                         var multipartFormData = new FormData();
      73             : 
      74             :                         foreach (var file in multipartProvider.Contents.Where(x => IsFile(x.Headers.ContentDisposition)))
      75             :                         {
      76             :                                 var name = UnquoteToken(file.Headers.ContentDisposition.Name);
      77             :                                 string fileName = FixFilename(file.Headers.ContentDisposition.FileName);
      78             :                                 string mediaType = file.Headers.ContentType.MediaType;
      79             : 
      80             :                                 using (var stream = await file.ReadAsStreamAsync())
      81             :                                 {
      82             :                                         byte[] buffer = ReadAllBytes(stream);
      83             :                                         if (buffer.Length > 0)
      84             :                                         {
      85             :                                                 multipartFormData.Add(name, new HttpFile(fileName, mediaType, buffer));
      86             :                                         }
      87             :                                 }
      88             :                         }
      89             : 
      90             :                         foreach (var part in multipartProvider.Contents.Where(x => x.Headers.ContentDisposition.DispositionType == "form-data"
      91             :                                                                                                                                   && !IsFile(x.Headers.ContentDisposition)))
      92             :                         {
      93             :                                 var name = UnquoteToken(part.Headers.ContentDisposition.Name);
      94             :                                 var data = await part.ReadAsStringAsync();
      95             :                                 multipartFormData.Add(name, data);
      96             :                         }
      97             : 
      98             :                         return multipartFormData;
      99             :                 } 
     100             : 
     101             :                 private bool IsFile(ContentDispositionHeaderValue disposition)
     102             :                 {
     103             :                         return !string.IsNullOrEmpty(disposition.FileName);
     104             :                 }
     105             : 
     106             :                 /// <summary>
     107             :                 /// Remove bounding quotes on a token if present
     108             :                 /// </summary>
     109             :                 private static string UnquoteToken(string token)
     110             :                 {
     111             :                         if (String.IsNullOrWhiteSpace(token))
     112             :                         {
     113             :                                 return token;
     114             :                         }
     115             : 
     116             :                         if (token.StartsWith("\"", StringComparison.Ordinal) && token.EndsWith("\"", StringComparison.Ordinal) && token.Length > 1)
     117             :                         {
     118             :                                 return token.Substring(1, token.Length - 2);
     119             :                         }
     120             : 
     121             :                         return token;
     122             :                 }
     123             : 
     124             :                 /// <summary>
     125             :                 /// Amend filenames to remove surrounding quotes and remove path from IE
     126             :                 /// </summary>
     127             :                 private static string FixFilename(string originalFileName)
     128             :                 {
     129             :                         if (string.IsNullOrWhiteSpace(originalFileName))
     130             :                                 return string.Empty;
     131             : 
     132             :                         var result = originalFileName.Trim();
     133             :                         
     134             :                         // remove leading and trailing quotes
     135             :                         result = result.Trim('"');
     136             : 
     137             :                         // remove full path versions
     138             :                         if (result.Contains("\\"))
     139             :                                 result = Path.GetFileName(result);
     140             : 
     141             :                         return result;
     142             :                 }
     143             : 
     144             :                 private byte[] ReadAllBytes(Stream input)
     145             :                 {
     146             :                         using (var stream = new MemoryStream())
     147             :                         {
     148             :                                 input.CopyTo(stream);
     149             :                                 return stream.ToArray();
     150             :                         }
     151             :                 }
     152             :         }
     153             : }

Generated by: LCOV version 1.10