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

使用ASP.Net Web API进行多部分表单POST

发布时间:2020-12-16 00:07:43 所属栏目:asp.Net 来源:网络整理
导读:我有一个改编自 A guide to asynchronous file uploads in ASP.NET Web API RTM 的POST ASP.Net Web Api方法. 我遇到了故障的任务问题,在第一个请求被触发并完成后触发了所有请求. 这是场景:我有一个示例页面,它将文件和其他参数一起发布到Web API Post方法
我有一个改编自 A guide to asynchronous file uploads in ASP.NET Web API RTM的POST ASP.Net Web Api方法.

我遇到了故障的任务问题,在第一个请求被触发并完成后触发了所有请求.

这是场景:我有一个示例页面,它将文件和其他参数一起发布到Web API Post方法.它第一次正常工作,文件上传.但是,所有后续请求都会在故障状态下结束任务.我得到“MIME多部分流的意外结束. MIME多部分消息不完整.“任何想法为什么?

下面粘贴的是我的Post方法的源代码,示例html表单和Aggregate Exception.

public Task<HttpResponseMessage> Post([FromUri]string memberNumber)
    {
        // Check if the request contains multipart/form-data.
        if (!Request.Content.IsMimeMultipartContent())
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }

        string root = HttpContext.Current.Server.MapPath("~/App_Data");
        var provider = new MultipartFormDataStreamProvider(root);

        // Read the form data and return an async task.
        var task = Request.Content.ReadAsMultipartAsync(provider).
            ContinueWith(t =>
            {
                if (t.IsFaulted || t.IsCanceled)
                {
                    throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.InternalServerError,t.Exception));
                }

                return Request.CreateResponse(HttpStatusCode.OK,new MyModel());
            });

        return task;
    }

我正在使用这样的示例表单解雇此web api:

<form name="form1" method="post" enctype="multipart/form-data" action="api/claims/asd123" style="margin:auto;width:500px;">
    <div>
        <label for="HCPracticeNumber">HC Pratice Number:</label>
        <input type="text" name="HCPracticeNumber" id="HCPracticeNumber"/>
    </div>
    <div>
        <label for="ServiceDate">Service/Treatment date:</label>
        <input type="text" name="ServiceDate" id="ServiceDate"/>
    </div>
    <div>
        <label for="AmountClaimed">Amount Claimed:</label>
        <input type="text" name="AmountClaimed" id="AmountClaimed"/>
    </div>
    <div>
        <label for="Image">Image Attachment:</label>
        <input name="Image" type="file" />
    </div>
    <div>
        <input type="submit" value="Submit" />
    </div>
</form>

返回的AggregateException如下:

<Error>
<Message>An error has occurred.</Message>
    <ExceptionMessage>One or more errors occurred.</ExceptionMessage>
    <ExceptionType>System.AggregateException</ExceptionType>
    <StackTrace/>
    <InnerException>
        <Message>An error has occurred.</Message>
        <ExceptionMessage>
            Unexpected end of MIME multipart stream. MIME multipart message is not complete.
        </ExceptionMessage>
        <ExceptionType>System.IO.IOException</ExceptionType>
        <StackTrace>
            at System.Net.Http.Formatting.Parsers.MimeMultipartBodyPartParser.<ParseBuffer>d__0.MoveNext() at System.Net.Http.HttpContentMultipartExtensions.MoveNextPart(MultipartAsyncContext context)
        </StackTrace>
    </InnerException>
</Error>

更新:

在Filip在他的博客网站上提出建议后,我修改了post方法,将流位置重置为0,如下所示:

Stream reqStream = Request.Content.ReadAsStreamAsync().Result;
        if (reqStream.CanSeek)
        {
            reqStream.Position = 0;
        }
        var task = Request.Content.ReadAsMultipartAsync(provider).
            ContinueWith(t =>
            {
                if (t.IsFaulted || t.IsCanceled)
                {
                    throw new HttpResponseException(
                    Request.CreateErrorResponse(HttpStatusCode.InternalServerError,new MyModel());

            });

但是,这是非常有气质的代码.它的工作有时它不会在其他时间.换句话说,它并没有完全解决问题.

解决方法

事实证明,正如Filip在评论中所建议的那样,我从 Implementing Message Handlers To Track Your ASP .net Web API Usage改编的Web API使用处理程序正在读取内容正文,因此在我的POST方法中处理请求时,会在流上找到位置搜索器.

因此,如果请求的类型为IsMimeMultipartContent,我向WebApiUsageHandler添加了一个条件语句,以便不读取请求主体.这解决了这个问题.

更新

我想用Filip通过电子邮件向我建议的另一个选项更新答案,以便记录:

如果您在API使用处理程序中使用此代码,则在读取正文之前:

//read content into a buffer
   request.Content.LoadIntoBufferAsync().Wait();

   request.Content.ReadAsStringAsync().ContinueWith(t =>
   {
       apiRequest.Content = t.Result;
       _repo.Add(apiRequest);
   });

请求将被缓冲,并且可以读取两次,因此可以在管道中进一步上传.希望这可以帮助.

(编辑:李大同)

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

    推荐文章
      热点阅读