File Upload with Additonal Form Data to Web Api from MVC

匿名 (未验证) 提交于 2019-12-03 03:06:01

问题:

I am trying to upload a file with additional form data and post to Web API via MVC but i couldn't accomplish.

MVC Side

Firstly i got the submitted form at MVC. Here is the action for this.

    [HttpPost]             public async Task<ActionResult> Edit(BrandInfo entity) {                  try {                     byte[] logoData = null;                     if(Request.Files.Count > 0) {                         HttpPostedFileBase logo = Request.Files[0];                         logoData = new byte[logo.ContentLength];                         logo.InputStream.Read(logoData, 0, logo.ContentLength);                         entity.Logo = logo.FileName;                         entity = await _repo.Update(entity.BrandID, entity, logoData);                     }                     else                         entity = await _repo.Update(entity,entity.BrandID);                     return RedirectToAction("Index", "Brand");                 }                 catch(HttpApiRequestException e) { // logging, etc                                        return RedirectToAction("Index", "Brand");                 }             }

Below code post the Multipartform to Web API

string requestUri = UriUtil.BuildRequestUri(_baseUri, uriTemplate, uriParameters: uriParameters);             MultipartFormDataContent formData = new MultipartFormDataContent();             StreamContent streamContent = null;             streamContent = new StreamContent(new MemoryStream(byteData));                         streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") {                 FileName = "\"" + fileName + "\"",                 Name = "\"filename\""             };             streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");             formData.Add(streamContent);             formData.Add(new ObjectContent<TRequestModel>(requestModel, _writerMediaTypeFormatter), "entity");             return _httpClient.PutAsync(requestUri, formData).GetHttpApiResponseAsync<TResult>(_formatters);

As you can see i am trying to send file data and object with same MultipartFormDataContent. I couldn't find better way to send my entity as ObjectContent. Also i am using JSON.Net Serializer

Regarding to fiddler, post seems successfull.

Web API Side

Finally i am catching post at Web API side and trying to parse but i couldn't. Because MultipartFormDataStreamProvider's FileData and FormData collections are allways empty.

[HttpPut]         public void UpdateWithLogo(int id) {             if(Request.Content.IsMimeMultipartContent()) {                 var x = 1; // this code has no sense, only here to check IsMimeMultipartContent             }                string root = HttpContext.Current.Server.MapPath("~/App_Data");             var provider = new MultipartFormDataStreamProvider(root);              try {                 // Read the form data.                  Request.Content.ReadAsMultipartAsync(provider);                   foreach(var key in provider.FormData.AllKeys) {                      foreach(var val in provider.FormData.GetValues(key)) {                          _logger.Info(string.Format("{0}: {1}", key, val));                      }                  }                  // This illustrates how to get the file names.                 foreach(MultipartFileData file in provider.FileData) {                     _logger.Info(file.Headers.ContentDisposition.FileName);                     _logger.Info("Server file path: " + file.LocalFileName);                 }                            }             catch(Exception e) {                 throw new HttpApiRequestException("Error", HttpStatusCode.InternalServerError, null);             }                       }

I hope you can help to find my mistake.

UPDATE

I also realized that, if i comment out StreamContent or ObjectContent and only add StringContent, still i can't get anything from MultipartFormDataStreamProvider.

回答1:

Finally i resolved my problem and it was all about async :)

As you can see at API action method i had called ReadAsMultipartAsync method synchrously but this was a mistake. I had to call it with ContinueWith so after i changed my code like below my problem solved.

var files = Request.Content.ReadAsMultipartAsync(provider).ContinueWith<HttpResponseMessage>(task => {                     if(task.IsFaulted)                         throw task.Exception; // do additional stuff });


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!