web-dev-qa-db-fra.com

AngularJS Chargement d'une image avec ng-upload

J'essaie de télécharger un fichier dans AngularJS en utilisant ng-upload, mais je rencontre des problèmes. Mon html ressemble à ceci:

<div class="create-article" ng-controller="PostCreateCtrl">
        <form ng-upload method="post" enctype="multipart/form-data" action="/write" >
            <fieldset>
                <label>Category</label>
                <select name="category_id" class="">
                    <option value="0">Select A Category</option>
                    <?php foreach($categories as $category): ?>
                        <option value="<?= $category -> category_id; ?>"><?= $category -> category_name; ?></option>
                    <?php endforeach; ?>
                </select>

                <label>Title</label>
                <input type="text" class="title span5" name="post_title"
                       placeholder="A catchy title here..."
                       value="<?= $post -> post_title; ?>" />

                <label>Attach Image</label>
                <input type="file" name="post_image" />

                 <a href='javascript:void(0)'  class="upload-submit: uploadPostImage(contents, completed)" >Crop Image</a>

                <label>Body</label>
                <div id="container">
                <textarea id="mytextarea" wrap="off" name="post_content" class="span7" placeholder="Content..."><?= $post -> post_content; ?></textarea>
                </div>
                <div style='clear:both;'></div>
                <label>Preview</label>
                <div id='textarea-preview'></div>

            </fieldset>
            <div class="span7" style="margin: 0;">
                <input type="submit" class="btn btn-success" value="Create Post" />
            <input type="submit" class="btn btn-warning pull-right draft" value="Save as Draft" />
            </div>

        </form>
    </div>

Et mon contrôleur js ressemble à ceci:

ClabborApp.controller("PostCreateCtrl", ['$scope', 'PostModel',
function($scope, PostModel) {

    $scope.uploadPostImage = function(contents, completed) {
        console.log(completed);
        alert(contents);
    }

}]);

Le problème auquel je suis confronté est lorsque l'image de rognage est atteinte et qu'elle exécute uploadPostImage, elle télécharge l'intégralité du formulaire. Pas de comportement souhaité mais je peux le faire fonctionner. Le gros problème réside dans le js, la fonction uploadPostImage des paramètres 'contenus' est toujours indéfinie, même lorsque le paramètre 'completed' revient à true.

L'objectif est de ne télécharger qu'une image à recadrer. Qu'est-ce que je fais mal dans ce processus?

32
Devin Dixon

Il y a peu ou pas de documentation sur angular pour le téléchargement de fichiers. De nombreuses solutions nécessitent des directives personnalisées, ainsi que d'autres dépendances (jquery in primis ... juste pour télécharger un fichier ...). Après plusieurs essais, je 'ai trouvé cela avec just angularjs (testé sur v.1.0.6)

html

<input type="file" name="file" onchange="angular.element(this).scope().uploadFile(this.files)"/>

Angularjs (1.0.6) ne supporte pas ng-model sur les balises "input-file", vous devez donc le faire de manière "native" transmettre tous les fichiers (éventuellement) sélectionnés de l'utilisateur.

contrôleur

$scope.uploadFile = function(files) {
    var fd = new FormData();
    //Take the first selected file
    fd.append("file", files[0]);

    $http.post(uploadUrl, fd, {
        withCredentials: true,
        headers: {'Content-Type': undefined },
        transformRequest: angular.identity
    }).success( ...all right!... ).error( ..damn!... );

};

La partie cool est le type de contenu non défini et le transformRequest: angular.identity qui donne à $ http la possibilité de choisir le "type de contenu" approprié et de gérer les limites nécessaires au traitement des données en plusieurs parties.

60
Fabio Bonfante

Vous pouvez essayer le plugin ng-file-upload angularjs (au lieu de ng-upload ).

Il est assez facile de configurer et de gérer les spécificités angularjs. Il prend également en charge la progression, annuler, glisser-déposer et est un navigateur croisé.

html

<!-- Note: MUST BE PLACED BEFORE angular.js-->
<script src="ng-file-upload-shim.min.js"></script> 
<script src="angular.min.js"></script>
<script src="ng-file-upload.min.js"></script> 

<div ng-controller="MyCtrl">
  <input type="file" ngf-select="onFileSelect($files)" multiple>
</div>

JS:

//inject angular file upload directives and service.
angular.module('myApp', ['ngFileUpload']);

var MyCtrl = [ '$scope', '$upload', function($scope, $upload) {
  $scope.onFileSelect = function($files) {
    //$files: an array of files selected, each file has name, size, and type.
    for (var i = 0; i < $files.length; i++) {
      var file = $files[i];
      $scope.upload = $upload.upload({
        url: 'server/upload/url', //upload.php script, node.js route, or servlet url
        data: {myObj: $scope.myModelObj},
        file: file,
      }).progress(function(evt) {
        console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
      }).then(function(response) {
        var data = response.data;
        // file is uploaded successfully
        console.log(data);
      });
    }
  };
}];
19
danial

Dans mon cas, les méthodes mentionnées ci-dessus fonctionnent bien avec php, mais lorsque j'essaie de télécharger des fichiers avec ces méthodes dans node.js, j'ai un problème. Ainsi, au lieu d’utiliser $ http ({.., .., ...}), utilisez le jquery ajax normal.

Pour sélectionner le fichier, utilisez cette

<input type="file" name="file" onchange="angular.element(this).scope().uploadFile(this)"/>

Et dans le contrôleur

$scope.uploadFile = function(element) {   
var data = new FormData();
data.append('file', $(element)[0].files[0]);
jQuery.ajax({
      url: 'brand/upload',
      type:'post',
      data: data,
      contentType: false,
      processData: false,
      success: function(response) {
      console.log(response);
      },
      error: function(jqXHR, textStatus, errorMessage) {
      alert('Error uploading: ' + errorMessage);
      }
 });   
};
1
Tek Raj Pant