2016-09-24 2 views
0

J'essaie de créer une API Web Asp.net pour poster des fichiers. J'ai trouvé l'exemple suivant dans https://code.msdn.microsoft.com/AngularJS-with-Web-API-22f62a6eTéléchargement d'un fichier et enregistrement des valeurs de saisie de texte en un clic?

La méthode API Web est:

[RoutePrefix("api/photo")] 
public class PhotoController : ApiController 
{ 
    private IPhotoManager photoManager; 

    public PhotoController() 
     : this(new LocalPhotoManager(HttpRuntime.AppDomainAppPath + @"\Album")) 
    {    
    } 

    public PhotoController(IPhotoManager photoManager) 
    { 
     this.photoManager = photoManager; 
    } 

    // GET: api/Photo 
    public async Task<IHttpActionResult> Get() 
    { 
     var results = await photoManager.Get(); 
     return Ok(new { photos = results }); 
    } 

    // POST: api/Photo 
    public async Task<IHttpActionResult> Post() 
    { 
     // Check if the request contains multipart/form-data. 
     if(!Request.Content.IsMimeMultipartContent("form-data")) 
     { 
      return BadRequest("Unsupported media type"); 
     } 

     try 
     { 
      var photos = await photoManager.Add(Request); 
      return Ok(new { Message = "Photos uploaded ok", Photos = photos }); 
     } 
     catch (Exception ex) 
     { 
      return BadRequest(ex.GetBaseException().Message); 
     } 

    } 

Et le code fichier Uploader html. (J'ai ajouté une entrée de texte <input type="text" id="test" value="testit" /> pour le test

<form name="newPhotosForm" role="form" enctype="multipart/form-data" ng-disabled="appStatus.busy || photoManagerStatus.uploading"> 
    <div class="form-group" ng-hide="hasFiles"> 
     <label for="newPhotos">select and upload new photos</label> 
     <input type="file" id="newPhotos" class="uploadFile" accept="image/*" eg-files="photos" has-files="hasFiles" multiple> 
     <input type="text" id="test" value="testit" /> <!--- Added a text input for test --> 
    </div> 
    <div class="form-group" ng-show="hasFiles && !photoManagerStatus.uploading"> 
     <ul class="list-inline"> 
      <li><strong>files:</strong></li> 
      <li ng-repeat="photo in photos"> {{photo.name}}</li> 
     </ul> 
     <input class="btn btn-primary" type="button" eg-upload="upload(photos)" value="upload"> 
     <input class="btn btn-warning" type="reset" value="cancel" /> 
    </div> 
    <div class="form-group" ng-show="photoManagerStatus.uploading"> 
     <p class="help-block">uploading</p> 
    </div> 
</form> 

Le JS upload Fonction:

function upload(photos) 
{ 
    service.status.uploading = true; 
    appInfo.setInfo({ busy: true, message: "uploading photos" });    

    var formData = new FormData(); 

    angular.forEach(photos, function (photo) { 
     formData.append(photo.name, photo); 
    }); 

    return photoManagerClient.save(formData) 
           .$promise 
           .then(function (result) { 
            if (result && result.photos) { 
             result.photos.forEach(function (photo) { 
              if (!photoExists(photo.name)) { 
               service.photos.push(photo); 
              } 
             }); 
            } 

            appInfo.setInfo({message: "photos uploaded successfully"}); 

            return result.$promise; 
           }, 
           function (result) { 
            appInfo.setInfo({message: "something went wrong: " + result.data.message}); 
            return $q.reject(result); 
           }) 
           ['finally'](
           function() { 
            appInfo.setInfo({ busy: false });            
            service.status.uploading = false; 
           }); 
} 

Cependant, il semble que la valeur de l'entrée ajoutée test ne peut pas être transmise au code API Web?

Répondre

1

Vous devez ajouter une classe DTO/POCO personnalisée, définir les valeurs, puis la transmettre comme paramètre à votre méthode de publication. Comme le fichier n'est pas un type simple, MediaTypeFormatter de webAPI ne fonctionnera pas par défaut. Vous devez donc créer votre MediaTypeFormatter personnalisé.

échantillon POCO classe

Public Class Attachment 
{ 
    public string Input {get;set;} 
    public byte[] Content{get;set;} 
} 

formatter Custom Media comme ci-dessous

public class CustomFormatter : MediaTypeFormatter 
{ 
    /// <summary> 
    /// 
    /// </summary> 
    public CustomFormatter() 
    { 
     SupportedMediaTypes.Add(new MediaTypeHeaderValue("multipart/form-data")); 
    } 

    public override bool CanReadType(Type type) 
    { 
     return type == typeof(Attachment); 
    } 

    public override bool CanWriteType(Type type) 
    { 
     return false; 
    } 

    public async override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger) 
    { 
     var provider = await content.ReadAsMultipartAsync(); 

     var modelContent = provider.Contents 
      .FirstOrDefault(c => c.Headers.ContentType.MediaType == "application/json"); 

     var attachment = await modelContent.ReadAsAsync<Attachment>(); 

     var fileContents = provider.Contents 
      .Where(c => c.Headers.ContentType.MediaType == "image/jpeg").FirstOrDefault(); // or whatever is the type of file to upload 

     attachment.Content = await fileContents.ReadAsByteArrayAsync(); 

     return attachment; 

    } 
} 

Enregistrez le formatter des médias personnalisés:

private void ConfigureWebApi(HttpConfiguration config) 
{ 
    //other code here 
    config.Formatters.Add(new CustomFormatter()); 
} 

Passez Poco à votre API Web Controller

public async Task<IHttpActionResult> Post(Attachment attachment) 
{ 

Je n'ai pas testé dans Visual Studio, mais ceci est l'approche que vous devez suivre

Plus d'informations ici: http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters

Et un échantillon ici http://blog.marcinbudny.com/2014/02/sending-binary-data-along-with-rest-api.html#.V5MDDzV7qYg