适用于ASP.NET Core 2的MultipartFormDataStreamProvider
发布时间:2020-12-16 03:24:54 所属栏目:asp.Net 来源:网络整理
导读:我正在将项目从ASP.NET MVC 5迁移到ASP.NET Core 2,并且遇到了有关MultipartFormDataStreamProvider的一些问题 据我所知,它还不是.NET Core的一部分,因此无法使用.我试图解决的问题是使用Sendgrid,解析电子邮件的代码的一部分. .NET MVC 5代码如下所示 [Http
我正在将项目从ASP.NET MVC 5迁移到ASP.NET Core 2,并且遇到了有关MultipartFormDataStreamProvider的一些问题
据我所知,它还不是.NET Core的一部分,因此无法使用.我试图解决的问题是使用Sendgrid,解析电子邮件的代码的一部分. .NET MVC 5代码如下所示 [HttpPost] public async Task<HttpResponseMessage> Post() { var root = HttpContext.Current.Server.MapPath("~/App_Data"); var provider = new MultipartFormDataStreamProvider(root); await Request.Content.ReadAsMultipartAsync(provider); var email = new Email { Dkim = provider.FormData.GetValues("dkim").FirstOrDefault(),To = provider.FormData.GetValues("to").FirstOrDefault(),Html = provider.FormData.GetValues("html").FirstOrDefault() } } 此代码是从Sendgrid API文档:https://sendgrid.com/docs/Integrate/Code_Examples/Webhook_Examples/csharp.html获取的代码段 所以我一直在摆弄这个问题,试图想出一个解决方案,但我完全陷入困境.最接近解决方案的是使用Request.Form,例如 To = form["to"].SingleOrDefault(),From = form["from"].SingleOrDefault() 但是,这仅适用于通过ARC(或任何其他REST-API测试程序)的ARC REST客户端插件发送数据.此解决方案也将无法处理诸如图像之类的附件. 所以我转向StackOverflow社区,希望有人有一些指针或解决方案,如何将其迁移到.NET Core 2. 提前致谢! 解决方法
这是我到目前为止的解决方案.它仍然是一项正在进行的工作,例如,在处理附件方面,但它已成功解析电子邮件.它从Wade的博客中大量借鉴了在
https://dotnetcoretutorials.com/2017/03/12/uploading-files-asp-net-core/上的ASP.NET Core上传文件
[HttpPost] [DisableFormValueModelBinding] [Route("v4/ProcessEmail")] public async Task<IActionResult> ParseSendGridInboundWebHook() { FormValueProvider formModel; using (var stream = System.IO.File.Create("c:tempmyfile.temp")) { formModel = await _context.HttpContext.Request.StreamFile(stream); } var viewModel = new SendGridEmailDTO(); var bindingSuccessful = await TryUpdateModelAsync(viewModel,prefix: "",valueProvider: formModel); if (!bindingSuccessful) { if (!ModelState.IsValid) { return new BadRequestResult(); } } <your code here> return new OkResult(); } public static class MultipartRequestHelper { // Content-Type: multipart/form-data; boundary="----WebKitFormBoundarymx2fSWqWSd0OxQqq" // The spec says 70 characters is a reasonable limit. public static string GetBoundary(MediaTypeHeaderValue contentType,int lengthLimit) { var boundary = HeaderUtilities.RemoveQuotes(contentType.Boundary); if (string.IsNullOrWhiteSpace(boundary.Value)) { throw new InvalidDataException("Missing content-type boundary."); } if (boundary.Length > lengthLimit) { throw new InvalidDataException( $"Multipart boundary length limit {lengthLimit} exceeded."); } return boundary.Value; } public static bool IsMultipartContentType(string contentType) { return !string.IsNullOrEmpty(contentType) && contentType.IndexOf("multipart/",StringComparison.OrdinalIgnoreCase) >= 0; } public static bool HasFormDataContentDisposition(ContentDispositionHeaderValue contentDisposition) { // Content-Disposition: form-data; name="key"; return contentDisposition != null && contentDisposition.DispositionType.Equals("form-data") && string.IsNullOrEmpty(contentDisposition.FileName.Value) && string.IsNullOrEmpty(contentDisposition.FileNameStar.Value); } public static bool HasFileContentDisposition(ContentDispositionHeaderValue contentDisposition) { // Content-Disposition: form-data; name="myfile1"; filename="Misc 002.jpg" return contentDisposition != null && contentDisposition.DispositionType.Equals("form-data") && (!string.IsNullOrEmpty(contentDisposition.FileName.Value) || !string.IsNullOrEmpty(contentDisposition.FileNameStar.Value)); } } public static class FileStreamingHelper { private static readonly FormOptions _defaultFormOptions = new FormOptions(); public static async Task<FormValueProvider> StreamFile(this HttpRequest request,Stream targetStream) { if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType)) { throw new Exception($"Expected a multipart request,but got {request.ContentType}"); } // Used to accumulate all the form url encoded key value pairs in the // request. var formAccumulator = new KeyValueAccumulator(); string targetFilePath = null; var boundary = MultipartRequestHelper.GetBoundary( MediaTypeHeaderValue.Parse(request.ContentType),_defaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary,request.Body); var section = await reader.ReadNextSectionAsync(); while (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition,out var contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { await section.Body.CopyToAsync(targetStream); } else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition)) { // Content-Disposition: form-data; name="key" // // value // Do not limit the key name length here because the // multipart headers length limit is already in effect. var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name); var encoding = GetEncoding(section); using (var streamReader = new StreamReader( section.Body,encoding,detectEncodingFromByteOrderMarks: true,bufferSize: 1024,leaveOpen: true)) { // The value length limit is enforced by MultipartBodyLengthLimit var value = await streamReader.ReadToEndAsync(); if (String.Equals(value,"undefined",StringComparison.OrdinalIgnoreCase)) { value = String.Empty; } formAccumulator.Append(key.Value,value); if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit) { throw new InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded."); } } } } // Drains any remaining section body that has not been consumed and // reads the headers for the next section. section = await reader.ReadNextSectionAsync(); } // Bind form data to a model var formValueProvider = new FormValueProvider( BindingSource.Form,new FormCollection(formAccumulator.GetResults()),CultureInfo.CurrentCulture); return formValueProvider; } private static Encoding GetEncoding(MultipartSection section) { MediaTypeHeaderValue mediaType; var hasMediaTypeHeader = MediaTypeHeaderValue.TryParse(section.ContentType,out mediaType); // UTF-7 is insecure and should not be honored. UTF-8 will succeed in // most cases. if (!hasMediaTypeHeader || Encoding.UTF7.Equals(mediaType.Encoding)) { return Encoding.UTF8; } return mediaType.Encoding; } } public class SendGridEmailDTO { public string Dkim { get; set; } public string To { get; set; } public string Html { get; set; } public string From { get; set; } public string Text { get; set; } public string SenderIp { get; set; } public string Envelope { get; set; } public int Attachments { get; set; } public string Subject { get; set; } public string Charsets { get; set; } public string Spf { get; set; } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- asp.net – HTTP错误404.4 – 未找到您要查找的资源没有与之
- 【Asp.Net MVC+EF+三层架构】详解(三)MVC VS 三层架构
- asp.net-mvc – MVC 4 ModelBinder
- asp.net-mvc – 属性的自定义模型binder
- asp.net-mvc – 实时ASP.NET MVC Web应用程序
- .NET Core采用的全新配置系统[4]: “Options模式”下各种类
- .net – 类库项目中特定于语言的资源文件的问题
- 谈谈基于SQL Server 的Exception Handlingp[下篇]
- asp.net-mvc-2 – 覆盖“Html.EditorFor”上的类
- asp.net中DataBinding的可维护性最佳实践
推荐文章
站长推荐
热点阅读