加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

适用于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; }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读