web-dev-qa-db-fra.com

Angularjs comment télécharger des données de formulaire en plusieurs parties et un fichier?

Je suis un débutant en angular.js mais j'ai une bonne compréhension des bases.

Ce que je cherche à faire est de télécharger un fichier et certaines données de formulaire sous forme de données de formulaire en plusieurs parties. J'ai lu que ce n'est pas une caractéristique d'angular, cependant les bibliothèques tierces peuvent le faire. J'ai cloné un fichier de téléchargement angulaire via git, mais je ne parviens toujours pas à poster un formulaire simple et un fichier.

Quelqu'un peut-il s'il vous plaît fournir un exemple, HTML et JS de la façon de faire cela?

31
CodingIsAwesome

Tout d'abord

  1. Vous n'avez pas besoin de changements spéciaux dans la structure. Je veux dire: balises HTML.
<input accept="image/*" name="file" ng-value="fileToUpload"
       value="{{fileToUpload}}" file-model="fileToUpload"
       set-file-data="fileToUpload = value;" 
       type="file" id="my_file" />

1.2 créer sa propre directive,

.directive("fileModel",function() {
        return {
                restrict: 'EA',
                scope: {
                        setFileData: "&"
                },
                link: function(scope, ele, attrs) {
                        ele.on('change', function() {
                                scope.$apply(function() {
                                        var val = ele[0].files[0];
                                        scope.setFileData({ value: val });
                                });
                        });
                }
        }
})
  1. Dans le module avec $ httpProvider, ajoutez des dépendances telles que (Accepter, Type de contenu, etc.) avec multipart/form-data. (Suggestion serait, accepter la réponse au format JSON) Pour par exemple:

$ httpProvider.defaults.headers.post ['Accept'] = 'application/json, text/javascript'; $ httpProvider.defaults.headers.post ['Content-Type'] = 'multipart/form-data ; charset = utf-8 ';

  1. Créez ensuite une fonction distincte dans le contrôleur pour gérer l’appel de soumission de formulaire. comme pour par exemple ci-dessous le code:

  2. Dans la fonction de service, le paramètre "responseType" est utilisé à dessein pour que le serveur ne renvoie pas "byteerror".

  3. transformRequest, pour modifier le format de la requête avec une identité attachée.

  4. withCredentials: false, pour les informations d'authentification HTTP.

in controller:

  // code this accordingly, so that your file object 
  // will be picked up in service call below.
  fileUpload.uploadFileToUrl(file); 


in service:

  .service('fileUpload', ['$http', 'ajaxService',
    function($http, ajaxService) {

      this.uploadFileToUrl = function(data) {
        var data = {}; //file object 

        var fd = new FormData();
        fd.append('file', data.file);

        $http.post("endpoint server path to whom sending file", fd, {
            withCredentials: false,
            headers: {
              'Content-Type': undefined
            },
            transformRequest: angular.identity,
            params: {
              fd
            },
            responseType: "arraybuffer"
          })
          .then(function(response) {
            var data = response.data;
            var status = response.status;
            console.log(data);

            if (status == 200 || status == 202) //do whatever in success
            else // handle error in  else if needed 
          })
          .catch(function(error) {
            console.log(error.status);

            // handle else calls
          });
      }
    }
  }])
<script src="//unpkg.com/angular/angular.js"></script>
22
Prasad Shinde

C’est joli, il faut juste une copie de la page de démonstration de ce projet et montre le téléchargement d’un seul fichier lors de la soumission du formulaire avec la progression du téléchargement.

(function (angular) {
'use strict';

angular.module('uploadModule', [])
    .controller('uploadCtrl', [
        '$scope',
        '$upload',
        function ($scope, $upload) {
            $scope.model = {};
            $scope.selectedFile = [];
            $scope.uploadProgress = 0;

            $scope.uploadFile = function () {
                var file = $scope.selectedFile[0];
                $scope.upload = $upload.upload({
                    url: 'api/upload',
                    method: 'POST',
                    data: angular.toJson($scope.model),
                    file: file
                }).progress(function (evt) {
                    $scope.uploadProgress = parseInt(100.0 * evt.loaded / evt.total, 10);
                }).success(function (data) {
                    //do something
                });
            };

            $scope.onFileSelect = function ($files) {
                $scope.uploadProgress = 0;
                $scope.selectedFile = $files;
            };
        }
    ])
    .directive('progressBar', [
        function () {
            return {
                link: function ($scope, el, attrs) {
                    $scope.$watch(attrs.progressBar, function (newValue) {
                        el.css('width', newValue.toString() + '%');
                    });
                }
            };
        }
    ]);
 }(angular));

HTML

<form ng-submit="uploadFile()">
   <div class="row">
         <div class="col-md-12">
                  <input type="text" ng-model="model.fileDescription" />
                  <input type="number" ng-model="model.rating" />
                  <input type="checkbox" ng-model="model.isAGoodFile" />
                  <input type="file" ng-file-select="onFileSelect($files)">
                  <div class="progress" style="margin-top: 20px;">
                    <div class="progress-bar" progress-bar="uploadProgress" role="progressbar">
                      <span ng-bind="uploadProgress"></span>
                      <span>%</span>
                    </div>
                  </div>

                  <button button type="submit" class="btn btn-default btn-lg">
                    <i class="fa fa-cloud-upload"></i>
                    &nbsp;
                    <span>Upload File</span>
                  </button>
                </div>
              </div>
            </form>

EDIT: Ajout de la transmission d’un modèle au serveur dans le fichier post.

Les données de formulaire dans les éléments d’entrée seraient envoyées dans la propriété data de la publication et seraient disponibles sous forme de valeurs de formulaire normales.

21
Jon

Il est plus efficace d’envoyer les fichiers directement.

Le encodage en base64 de Content-Type: multipart/form-data Ajoute 33% de temps système supplémentaire. Si le serveur le prend en charge, il est plus efficace d’envoyer les fichiers directement:

Faire plusieurs demandes $http.post Directement à partir de FileList

$scope.upload = function(url, fileList) {
    var config = {
      headers: { 'Content-Type': undefined },
      transformResponse: angular.identity
    };
    var promises = fileList.map(function(file) {
      return $http.post(url, file, config);
    });
    return $q.all(promises);
};

Lors de l'envoi d'un POST avec un objet File , il est important de définir 'Content-Type': undefined. Le méthode d'envoi XHR sera alors détecter le objet File et définir automatiquement le type de contenu.


Démo de travail de la directive "select-ng-files" fonctionnant avec ng-model1

L'élément <input type=file> Ne fonctionne pas par défaut avec la directive ng-model . Il faut un directive personnalisée :

angular.module("app",[]);

angular.module("app").directive("selectNgFiles", function() {
  return {
    require: "ngModel",
    link: function postLink(scope,elem,attrs,ngModel) {
      elem.on("change", function(e) {
        var files = elem[0].files;
        ngModel.$setViewValue(files);
      })
    }
  }
});
<script src="//unpkg.com/angular/angular.js"></script>
  <body ng-app="app">
    <h1>AngularJS Input `type=file` Demo</h1>
    
    <input type="file" select-ng-files ng-model="fileList" multiple>
    
    <h2>Files</h2>
    <div ng-repeat="file in fileList">
      {{file.name}}
    </div>
  </body>
2
georgeawg

Vous pouvez utiliser cette méthode pour envoyer des images et des données de formulaire

<div class="form-group ml-5 mt-4" ng-app="myApp" ng-controller="myCtrl">
                    <label for="image_name">Image Name:</label>
                    <input type="text"   placeholder="Image name" ng-model="fileName" class="form-control" required>
                    <br>

                    <br>
                    <input id="file_src" type="file"   accept="image/jpeg" file-input="files"   >
                    <br>
                        {{file_name}}
            <img class="rounded mt-2 mb-2 " id="prvw_img" width="150" height="100" >
                    <hr>
                      <button class="btn btn-info" ng-click="uploadFile()">Upload</button>
                        <br>

                       <div ng-show = "IsVisible" class="alert alert-info w-100 shadow mt-2" role="alert">
              <strong> {{response_msg}} </strong>
            </div>
                            <div class="alert alert-danger " id="filealert"> <strong> File Size should be less than 4 MB </strong></div>
                    </div>

Code JS angulaire

    var app = angular.module("myApp", []);
 app.directive("fileInput", function($parse){
      return{
           link: function($scope, element, attrs){
                element.on("change", function(event){
                     var files = event.target.files;


                     $parse(attrs.fileInput).assign($scope, element[0].files);
                     $scope.$apply();
                });
           }
      }
 });
 app.controller("myCtrl", function($scope, $http){
      $scope.IsVisible = false;
      $scope.uploadFile = function(){
           var form_data = new FormData();
           angular.forEach($scope.files, function(file){
                form_data.append('file', file); //form file
                                form_data.append('file_Name',$scope.fileName); //form text data
           });
           $http.post('upload.php', form_data,
           {
                //'file_Name':$scope.file_name;
                transformRequest: angular.identity,
                headers: {'Content-Type': undefined,'Process-Data': false}
           }).success(function(response){
             $scope.IsVisible = $scope.IsVisible = true;
                      $scope.response_msg=response;
               // alert(response);
               // $scope.select();
           });
      }

 });
0
Ayan Bhattacharjee