AngularJS: ¿cómo implementar una simple carga de archivos con formulario multiparte?

Quiero hacer una publicación simple en varias partes desde AngularJS a un servidor node.js, el formulario debe contener un objeto JSON en una parte y una imagen en la otra parte (actualmente estoy publicando solo el objeto JSON con $ recurso)

Pensé que debería comenzar con input type = “file”, pero luego descubrí que AngularJS no puede vincularse a eso …

todos los ejemplos que puedo encontrar son para crear plugins jQuery para arrastrar y soltar. Quiero una simple carga de un archivo.

Soy nuevo en AngularJS y no me siento cómodo escribiendo mis propias directivas.

Una solución de trabajo real sin más dependencias que angularjs (probado con v.1.0.6)

html

 

Angularjs (1.0.6) no es compatible con ng-model en las tags “input-file”, por lo que debe hacerlo de forma nativa y pasar todos los archivos seleccionados (eventualmente) del usuario.

controlador

 $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 parte interesante es el tipo de contenido indefinido y el transformRequest: angular.identity que le dan a $ http la capacidad de elegir el “tipo de contenido” correcto y administrar el límite necesario al manejar datos multipartes.

Puede usar la directiva simple / liviana ng-file-upload . Admite arrastrar y soltar, progreso de archivos y carga de archivos para navegadores que no sean HTML5 con FileAPI flash shim

 

JS:

 //inject angular file upload directive. angular.module('myApp', ['ngFileUpload']); var MyCtrl = [ '$scope', 'Upload', function($scope, Upload) { $scope.onFileSelect = function($files) { Upload.upload({ url: 'my/upload/url', file: $files, }).progress(function(e) { }).then(function(data, status, headers, config) { // file is uploaded successfully console.log(data); }); }]; 

Acabo de tener este problema. Entonces hay algunos enfoques. El primero es que los nuevos navegadores admiten el

 var formData = new FormData(); 

Siga este enlace a un blog con información sobre cómo el soporte se limita a los navegadores modernos, pero de lo contrario resuelve completamente este problema.

De lo contrario, puede publicar el formulario en un iframe utilizando el atributo de destino. Cuando publique el formulario, asegúrese de establecer el objective en un iframe con su propiedad de visualización establecida en none. El objective es el nombre del iframe. (Solo para que sepas.)

espero que esto ayude

Es más eficiente enviar un archivo directamente.

La encoding 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:

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

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.

Para enviar varios archivos, consulte Hacer varias solicitudes de $http.post directamente desde una lista de archivos


Pensé que debería comenzar con input type = “file”, pero luego descubrí que AngularJS no puede vincularse a eso …

El elemento no funciona de forma predeterminada con la directiva ng-model . Necesita una directiva personalizada :

Demo de trabajo de la directiva “select-ng-files” que funciona con ng-model 1

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

AngularJS Input `type=file` Demo

Files

{{file.name}}

Sé que esta es una entrada tardía, pero he creado una directiva de carga simple. ¡Con lo cual puedes trabajar de inmediato!

  

ng-simple-carga más en Github con un ejemplo utilizando la API web.

Puede cargar mediante $resource asignando datos al atributo de parámetros de las actions de recursos de esta manera:

 $scope.uploadFile = function(files) { var fdata = new FormData(); fdata.append("file", files[0]); $resource('api/post/:id', { id: "@id" }, { postWithFile: { method: "POST", params: fdata, transformRequest: angular.identity, headers: { 'Content-Type': undefined } } }).postWithFile(fdata).$promise.then(function(response){ //successful },function(error){ //error }); }; 

Acabo de escribir una directiva simple (de uno existente, por supuesto) para un cargador simple en AngularJs.

(El complemento exacto de jQuery uploader es https://github.com/blueimp/jQuery-File-Upload )

Un cargador simple usando AngularJs (con implementación CORS)

(Aunque el lado del servidor es para PHP, también puedes cambiarlo nodo)

Me gustaría agregar una alternativa. Utilizando la carga de archivo angular. Puedes encontrar una explicación:

Puede encontrar una explicación detallada aquí: https://github.com/nervgh/angular-file-upload Un ejemplo: https://github.com/nervgh/angular-file-upload/tree/master/examples/simple