使用其他表单数据从MVC上传到Web Api的文件

时间:2013-03-26 09:07:55

标签: file-upload asp.net-mvc-4 asp.net-web-api multipartform-data

我正在尝试上传带有其他表单数据的文件,并通过MVC发布到Web API,但我无法完成。

MVC Side

首先,我在MVC收到了提交的表格。这是针对此的行动。

    [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");
                }
            }

下面的代码将Multipartform发布到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);

正如您所看到的,我正在尝试使用相同的MultipartFormDataContent发送文件数据和对象。我无法找到更好的方式将我的实体发送为ObjectContent。我也在使用JSON.Net Serializer

关于小提琴手,帖子看起来很成功。

PUT http://localhost:12836/api/brand/updatewithlogo/13 HTTP/1.1
Content-Type: multipart/form-data; boundary="10255239-d2a3-449d-8fad-2f31b1d00d2a"
Host: localhost:12836
Content-Length: 4341
Expect: 100-continue

--10255239-d2a3-449d-8fad-2f31b1d00d2a
Content-Disposition: form-data; filename="web-host-logo.gif"; name="filename"
Content-Type: application/octet-stream

GIF89a��L������X�������wW����������xH�U�)�-�k6�������v6�������̥�v�J���������7����V:�=#�ի�I(�xf�$�������
// byte data
// byte data
'pf�Y��y�ؙ�ڹ�(�;
--10255239-d2a3-449d-8fad-2f31b1d00d2a
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data; name=entity

{"BrandID":13,"AssetType":null,"AssetTypeID":2,"Logo":"web-host-logo.gif","Name":"Geçici Brand","Models":null,"SupplierBrands":null}
--10255239-d2a3-449d-8fad-2f31b1d00d2a--

Web API方

最后我在Web API端发帖并尝试解析,但我不能。因为MultipartFormDataStreamProvider的{​​{1}}和FileData集合总是空的。

FormData

我希望你能找到我的错误。

更新

我也意识到,如果我发表评论[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); } } StreamContent并且只添加了StringContent,我仍然无法从ObjectContent获得任何内容。

1 个答案:

答案 0 :(得分:5)

最后我解决了我的问题,这完全是关于 async :)

正如您在API动作方法中看到的那样,我已经同步地调用了ReadAsMultipartAsync方法,但这是一个错误。我不得不用ContinueWith来调用它,所以在我改变了我的代码后,我的问题就解决了。

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