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
- 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 });
});
});
}
}
})
- 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 '';
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:
En la función de servicio, maneje el parámetro "responseType" a propósito para que el servidor no arroje "byteerror".
transformRequest, para modificar el formato de solicitud con la identidad adjunta.
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>
<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.