w3schools form error javascript forms angularjs post multipartform-data

javascript - error - reset form angularjs



Angularjs cómo cargar datos de formulario multiparte y un archivo? (3)

Soy un principiante de angular.js pero tengo una buena comprensión de los conceptos básicos.

Lo que quiero hacer es cargar un archivo y algunos datos de formulario como datos de formulario multiparte. Leí que esta no es una característica de angular, sin embargo, las bibliotecas de terceros pueden hacerlo. He clonado angular-file-upload a través de git, sin embargo, todavía no puedo publicar un formulario simple y un archivo.

¿Puede alguien proporcionar un ejemplo, html y js de cómo hacer esto?


Es más eficiente enviar los archivos directamente.

La codificación base64 de Content-Type: multipart/form-data agrega un 33% adicional de gastos generales. Si el servidor lo admite, es más eficiente enviar los archivos directamente:

Hacer múltiples solicitudes de $http.post directamente desde una lista 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); };

Al enviar un POST con un objeto File , es importante establecer ''Content-Type'': undefined . El método de envío XHR detectará el objeto File y configurará automáticamente el tipo de contenido.

Demostración de trabajo de la directiva "entrada de archivos" que funciona con ng-model 1

El elemento <input type=file> no funciona de forma predeterminada con la directiva ng-model . Necesita una directiva personalizada :

angular.module("app",[]); angular.module("app").directive("filesInput", 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" files-input ng-model="fileList" multiple> <h2>Files</h2> <div ng-repeat="file in fileList"> {{file.name}} </div> </body>


Ante todo

  1. No necesita ningún cambio especial en la estructura. Quiero decir: etiquetas de entrada 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 crear su propia directiva,

.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. En el módulo con $ httpProvider agregue dependencia como (Aceptar, Tipo de contenido, etc.) con multipart / form-data. (La sugerencia sería, acepte la respuesta en formato json) Por ejemplo:

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

  1. A continuación, cree una función separada en el controlador para manejar la llamada de envío de formulario. como por ejemplo por debajo del código:

  2. En la función de servicio, maneje el parámetro "responseType" a propósito para que el servidor no arroje "byteerror".

  3. transformRequest, para modificar el formato de solicitud con la identidad adjunta.

  4. withCredentials: falso, para información de autenticación 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>


Esto es bastante solo una copia de esa página de demostración de proyectos y muestra la carga de un solo archivo en el formulario enviado con el progreso de la carga.

(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>

EDITAR: Agregó pasar un modelo al servidor en la publicación del archivo.

Los datos de formulario en los elementos de entrada se enviarán en la propiedad de datos de la publicación y estarán disponibles como valores de formulario normales.