Angularjs jak przesłać dane formularza wieloczęściowego i plik?

Jestem początkujący do angular.js ale mam dobre pojęcie o podstawach.

To, co chcę zrobić, to przesłać plik i niektóre dane formularza jako dane formularza wieloczęściowego. Czytałem, że nie jest to funkcja angular, jednak biblioteki stron trzecich mogą to zrobić. Sklonowałem angular-file-upload przez git, jednak nadal nie jestem w stanie opublikować prostego formularza i Pliku.

Może ktoś podać przykład, html i js jak to zrobić?

Author: Parthasarathy, 2014-06-27

3 answers

Po pierwsze

  1. nie potrzebujesz żadnych specjalnych zmian w strukturze. Mam na myśli: znaczniki wejściowe 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 utwórz własną dyrektywę,

.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. w module z $httpProvider dodaj zależność typu (Accept, Content-Type itp.) z multipart / form-data. (Sugestia brzmiałaby, Zaakceptuj odpowiedź w formacie json) Dla np.:

$httpProvider.domyślne.nagłówki.post ['Accept'] = ' application / json, tekst / javascript"; $httpProvider.domyślne.nagłówki.post ['Content-Type'] = 'multipart/form-data; charset=utf-8';

  1. Następnie utwórz oddzielną funkcję w kontrolerze do obsługi wywołania formularza submit. jak dla np. poniższego kodu:

  2. W funkcji service obsłuż param" responseType "celowo tak, aby serwer nie rzucał"byteerror".

  3. TransformRequest, aby zmodyfikować format żądania z dołączoną tożsamością.

  4. WithCredentials : false, dla informacji uwierzytelniania 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>
 20
Author: Prasad Shinde,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-24 17:51:28

To jest ładny musi tylko kopia tego projektu strona demo i pokazuje przesyłanie jednego pliku na formularzu wyślij z postępem przesyłania.

(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: Dodano przekazywanie modelu do serwera w pliku post.

Dane formularza w elementach wejściowych zostaną wysłane we właściwości data post i będą dostępne jako normalne wartości formularza.

 21
Author: Jon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-27 07:50:53

Bardziej wydajne jest wysyłanie plików bezpośrednio.

Kodowanie base64 z Content-Type: multipart/form-data dodaje dodatkowe 33% narzutu. Jeśli serwer go obsługuje, jest bardziej wydajne wysyłanie plików bezpośrednio:

Wykonywanie wielu $http.post żądań bezpośrednio z listy plików

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

Podczas wysyłania posta z obiektem File , Ważne jest, aby ustawić 'Content-Type': undefined. Metoda XHR send wykryje obiekt File i automatycznie ustawia typ zawartości.


Wersja demonstracyjna dyrektywy "select-ng-files", która działa z ng-model1

Element <input type=file> domyślnie nie działa z dyrektywą ng-model . Wymaga dyrektywy niestandardowej :

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
Author: georgeawg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-20 19:52:23