Line data Source code
1 : using System;
2 : using System.IO;
3 : using System.Linq;
4 : using System.Net;
5 : using System.Net.Http;
6 : using System.Net.Http.Formatting;
7 : using System.Net.Http.Headers;
8 : using System.Threading.Tasks;
9 : using Cqrs.WebApi.Formatters.FormMultipart.Converters;
10 : using Cqrs.WebApi.Formatters.FormMultipart.Infrastructure;
11 : using Cqrs.WebApi.Formatters.FormMultipart.Infrastructure.Logger;
12 :
13 : namespace Cqrs.WebApi.Formatters.FormMultipart
14 : {
15 : public class FormMultipartEncodedMediaTypeFormatter : MediaTypeFormatter
16 0 : {
17 : private const string SupportedMediaType = "multipart/form-data";
18 :
19 : private readonly MultipartFormatterSettings Settings;
20 :
21 0 : public FormMultipartEncodedMediaTypeFormatter(MultipartFormatterSettings settings = null)
22 : {
23 : Settings = settings ?? new MultipartFormatterSettings();
24 : SupportedMediaTypes.Add(new MediaTypeHeaderValue(SupportedMediaType));
25 : }
26 :
27 0 : public override bool CanReadType(Type type)
28 : {
29 : return true;
30 : }
31 :
32 0 : public override bool CanWriteType(Type type)
33 : {
34 : return true;
35 : }
36 :
37 0 : public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
38 : {
39 : base.SetDefaultContentHeaders(type, headers, mediaType);
40 :
41 : //need add boundary
42 : //(if add when fill SupportedMediaTypes collection in class constructor then receive post with another boundary will not work - Unsupported Media Type exception will thrown)
43 : if (headers.ContentType == null)
44 : {
45 : headers.ContentType = new MediaTypeHeaderValue(SupportedMediaType);
46 : }
47 : if (!String.Equals(headers.ContentType.MediaType, SupportedMediaType, StringComparison.OrdinalIgnoreCase))
48 : {
49 : throw new Exception("Not a Multipart Content");
50 : }
51 : if (headers.ContentType.Parameters.All(m => m.Name != "boundary"))
52 : {
53 : headers.ContentType.Parameters.Add(new NameValueHeaderValue("boundary", "Cqrs.WebApi.Formatters.FormMultipartBoundary1q2w3e"));
54 : }
55 : }
56 :
57 0 : public override async Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
58 : {
59 : var httpContentToFormDataConverter = new HttpContentToFormDataConverter();
60 : FormData multipartFormData = await httpContentToFormDataConverter.Convert(content);
61 :
62 : IFormDataConverterLogger logger;
63 : if (formatterLogger != null)
64 : logger = new FormatterLoggerAdapter(formatterLogger);
65 : else
66 : logger = new FormDataConverterLogger();
67 :
68 : var dataToObjectConverter = new FormDataToObjectConverter(multipartFormData, logger, Settings);
69 : object result = dataToObjectConverter.Convert(type);
70 :
71 : logger.EnsureNoErrors();
72 :
73 : return result;
74 : }
75 :
76 0 : public override async Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
77 : {
78 : if (!content.IsMimeMultipartContent())
79 : {
80 : throw new Exception("Not a Multipart Content");
81 : }
82 :
83 : var boudaryParameter = content.Headers.ContentType.Parameters.FirstOrDefault(m => m.Name == "boundary" && !String.IsNullOrWhiteSpace(m.Value));
84 : if (boudaryParameter == null)
85 : {
86 : throw new Exception("multipart boundary not found");
87 : }
88 :
89 : var objectToMultipartDataByteArrayConverter = new ObjectToMultipartDataByteArrayConverter(Settings);
90 : byte[] multipartData = objectToMultipartDataByteArrayConverter.Convert(value, boudaryParameter.Value);
91 :
92 : await writeStream.WriteAsync(multipartData, 0, multipartData.Length);
93 :
94 : content.Headers.ContentLength = multipartData.Length;
95 : }
96 : }
97 : }
|