7

Sto tentando di caricare un file con dati di modulo aggiuntivi e di postare all'API Web tramite MVC ma non sono riuscito a farlo.Caricamento file con dati modulo aggiuntivi a Web Api da MVC

MVC laterale

In primo luogo ho ottenuto il modulo inviato a MVC. Ecco l'azione per questo.

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

Di seguito il codice postale Multipartform al 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); 

Come potete vedere sto cercando di inviare i dati dei file e oggetto con lo stesso MultipartFormDataContent. Non ho trovato il modo migliore per inviare la mia entità come ObjectContent. Inoltre sto usando JSON.Net Serializer

Per quanto riguarda il violinista, il post sembra avere successo.

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 laterale

Infine sto prendendo piede posta al lato API Web e cercando di analizzare, ma non ci sono riuscita. Perché le collezioni FileData e FormData di MultipartFormDataStreamProvider sono sempre vuote.

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

Spero che tu possa aiutare a trovare il mio errore.

UPDATE

Ho anche capito che, se io commento StreamContent o ObjectContent e solo aggiungo StringContent, ancora non posso ottenere qualcosa da MultipartFormDataStreamProvider.

+0

Mi sono imbattuto in un problema leggermente diverso - il browser stava lasciando cadere i miei file dalla richiesta fino a quando non ho dato loro un nome/id. Ciò ha aiutato molto a diagnosticare il problema anche se – brichins

risposta

5

Finalmente ho risolto il mio problema ed è stato tutto su asincrona :)

Come si può vedere al metodo di azione API avevo chiamato ReadAsMultipartAsync metodo synchrously ma questo è stato un errore. Ho dovuto chiamarlo con ContinueWith quindi dopo aver cambiato il mio codice come sotto il mio problema risolto.

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

Se è stato risolto il problema, contrassegnarlo come accettato. – anaximander

+0

Ah, ho dimenticato quella restrizione. – anaximander

+1

Mi dispiace, sono un po 'confuso qui. Qual è il compito esattamente? e dovrei anche scrivere i dati del modulo anche qui? – Bobby5193

Problemi correlati