2016-12-28 5 views
0

J'ai une application Angular, écrite en Typescript, avec un backend ASP.Net Web Api. J'essaie d'utiliser la directive ng-file-upload (voir ce link pour plus de détails) pour télécharger un fichier image.Fin prévue du flux multi-parties MIME. Le message multi-parties MIME n'est pas complet

Je reçois une exception dans mon Web API méthode post:

"Fin inattendue du flux MIME multipart message MIME multipart est pas complète."

J'ai fait mes recherches et trouvé des problèmes similaires here - J'ai essayé d'implémenter la réponse de Landuber Kassa mais sans succès.

Aussi this bien que mon projet ne soit pas MVC et en tout cas cela ne fonctionnait pas. Je suis fraîche d'idées et apprécierais les pensées de la communauté. Je suis heureux d'envisager d'autres alternatives si je peux être indiqué dans la bonne direction.

Ash

My .Net méthode Post (mise en œuvre de l'idée de Landuber Kassa):

[RoutePrefix("BeaufortAppStore/api/Image")] 
public class ImageController : ApiController 
{ 

    #region Methods 

    #region Posts 

    [Route("UploadImage")] 
    [HttpPost] 
    public async Task<IHttpActionResult> UploadImage() 
    { 
     if (!Request.Content.IsMimeMultipartContent()) 
     { 
      throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); 
     } 

     var provider = new MultipartMemoryStreamProvider(); 

     Stream reqStream = Request.Content.ReadAsStreamAsync().Result; 
     MemoryStream tempStream = new MemoryStream(); 
     reqStream.CopyTo(tempStream); 

     tempStream.Seek(0, SeekOrigin.End); 
     StreamWriter writer = new StreamWriter(tempStream); 
     writer.WriteLine(); 
     writer.Flush(); 
     tempStream.Position = 0; 

     StreamContent streamContent = new StreamContent(tempStream); 
     foreach (var header in Request.Content.Headers) 
     { 
      streamContent.Headers.Add(header.Key, header.Value); 
     } 

     // Read the form data and return an async task. 
     await streamContent.ReadAsMultipartAsync(provider); // FAILS AT THIS POINT 
     foreach (var file in provider.Contents) 
     { 
      var filename = file.Headers.ContentDisposition.FileName.Trim('\"'); 
      var buffer = await file.ReadAsByteArrayAsync(); 
      //Do whatever you want with filename and its binary data. 
     } 
     return Ok(); 
    } 

    #endregion 

    #endregion 

Ma méthode de commande angulaire:

public upload(): void { 
     //Create config used in ng-file-upload 
     var config: IFileUploadConfigFile = { 
      data: this.file, url: "BeaufortAppStore/api/Image/UploadImage/", method: "POST" }; 
     this._dataService.uploadImage(config).then((result: any) => { 
      this.thumbnail = result.data; 
     }); 
    } 

Mon point de vue angulaire (vue partielle d'une directive) :

<div class="form-group"> 
<label for="file" class="control-label col-xs-2">Choose a file</label> 
<input id="file" type="file" name="file" class="form-control" ngf-select ngf-pattern="'image/*'" 
     ng-model="vm.file" /> 
<img style="width:100px;" ngf-thumbnail="thumbnail || '/thumb.jpg'" /> 
<button type="submit" ng-click="vm.upload()">Upload</button> 

Répondre

0

Essayez ceci dans C#:

[HttpPost] 
    [Route("Profile/Image")] 
    public Task<HttpResponseMessage> UploadImgProfile() 
      { 
       try 
       { 
        if (!ModelState.IsValid) return null; 

        var currentUser = _userUtils.GetCurrentUser(User); 
        if (currentUser == null) return null; 

        HttpRequestMessage request = this.Request; 
        if (!request.Content.IsMimeMultipartContent()) 
         throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.UnsupportedMediaType)); 

        string root = HttpContext.Current.Server.MapPath("~" + Constant.Application.User_Image_Directory); 

        bool exists = Directory.Exists(root); 
        if (!exists) 
         Directory.CreateDirectory(root); 

        var provider = new MultipartFormDataStreamProvider(root); 





    var task = request.Content.ReadAsMultipartAsync(provider). 
        ContinueWith<HttpResponseMessage>(o => 
        { 
         var finfo = new  FileInfo(provider.FileData.First().LocalFileName); 

      string guid = Guid.NewGuid().ToString(); 

      var fileName = guid + "_" + currentUser.IdOwin + ".jpg"; 

         File.Move(finfo.FullName, Path.Combine(root, fileName)); 

         return new HttpResponseMessage() 
         { 
          Content = new StringContent(Path.Combine(Constant.Application.User_Image_Directory, fileName)) 
         }; 
         } 
         ); 
        return task; 
       } 
       catch (Exception ex) 
       { 
        _logger.LogException(ex); 
        return null; 
       } 
      } 

Contrôleur angulaire:

//Upload Func 
      $scope.upload = function (files) { 
       if (files && files.length) { 
        for (var i = 0; i < files.length; i++) { 
         var file = files[i]; 
         $scope.uploading = true; 
         // $scope.imageName = file.name; 
         $upload.upload({ 
          url: enviroment.apiUrl + '/api/CurrentUser/Profile/Image', 
          //fields: { 'username': $scope.username }, 
          file: file 
         }).progress(function (evt) { 
          $scope.uploading = true; 
          var progressPercentage = parseInt(100.0 * evt.loaded/evt.total); 
          console.log('progress: ' + progressPercentage + '% ' + evt.config.file.name); 
          $scope.progress = progressPercentage; 
         }).success(function (data, status, headers, config) { 
          console.log('file ' + config.file.name + 'uploaded. Response: ' + data); 
          $scope.imageName = data; 
          $scope.uploading = false; 
          $scope.loadSuccess = true; 
          vm.uploadImage = false; 
          //AR 
          var reader = new FileReader(); 
          reader.onload = function (evt) { 
           $scope.$apply(function ($scope) { 
            $scope.myImage = evt.currentTarget.result; 
           }); 
          }; 
          reader.readAsDataURL(files[0]); 
          //END AR 
         }); 
        } 
       } 
      }; 


    // Stay on Listen upload file 
    $scope.$watch('files', function (evt) { 
     $scope.upload($scope.files); 
    }); 

HTML:

<div class="row"> 
           <!--UPLOAD--> 
           <div class="up-buttons"> 

            <div class="clearfix visible-xs-block"></div> 
            <div class="col-md-12 col-lg-12 col-sm-12 col-xs-12 text-center box-upload-image" data-ng-show="profileCtrl.uploadImage"> 
             <br /> 
             <div id="imgDragDrop" ng-file-drop ng-model="files" 
              drag-over-class="dragover" 
              accept="image/*"> 

              <div class="cropArea-bkg"> 
               <h4> 
                <span class="mdi mdi-account mdi-48px"></span> 
                <br /><br /> 
                Carica immagine profilo 
               </h4> 

               <p>Trascina qui la tua immagine, oppure</p> 

               <div ng-file-select="" ng-model="files" class="btn btn-secondary" ng-accept="'*.pdf,*.jpg,*.png'" tabindex="0"> 
                Sfoglia sul tuo computer 
               </div><br> 
              </div> 
             </div> 
             <div ng-no-file-drop class="well bg-danger">File Drag/Drop non è supportato da questo browser</div> 
             <br /> 
             <div class="text-center"> 
              <div class="progress" ng-show="uploading"> 
               <div class="progress-bar progress-bar-striped" role="progressbar" aria-valuenow="{{ ::progress }}" aria-valuemin="0" aria-valuemax="100" style="width: {{::progress}}% "> 
                <span class="sr-only">{{ ::progress }}% Complete</span> 
               </div> 
              </div> 
             </div> 

            </div> 

            <!--END UPLOAD--> 

           </div> 
          </div> 
+0

Merci pour la réponse rapide. Avant de l'essayer, pouvez-vous expliquer un peu ce qui est différent dans cette approche? –

+0

Fondamentalement, il s'agit d'une façon testée au combat de récupérer un contenu de téléchargement mutipart à partir d'un téléchargement angulaire ... il prend le format correct de la this.Request et avec une tâche asynchrone, il génère un nom (avec un guid aléatoire pour ne pas écraser ou aller en exception si quelqu'un télécharge la même image avec le même nom d'autre) –

+0

Je vais vous montrer aussi le contrôleur (Angular) et le html si vous en avez besoin ..et soyez sûr de votre méthode de publication (vérifiez sur la console en chrome .. si le format est correct .. si ce n'est pas essayer d'écraser l'en-tête de la demande) –