AngularJS: como implementar um simples upload de arquivo com formulário multiparte?

Eu quero fazer uma simples postagem de formulário multipartes do AngularJS para um servidor node.js, o formulário deve conter um object JSON em uma parte e uma imagem na outra parte, (atualmente estou postando apenas o object JSON com $ resource)

Eu imaginei que deveria começar com a input type = “file”, mas depois descobri que o AngularJS não pode se ligar a isso.

Todos os exemplos que posso encontrar são para wraping plugins jQuery para arrastar e soltar. Eu quero um simples upload de um arquivo.

Sou novo no AngularJS e não me sinto confortável em escrever minhas próprias diretrizes.

Uma solução de trabalho real sem outras dependencies além do angularjs (testado com a v.1.0.6)

html

 

Angularjs (1.0.6) não suporta ng-model em tags “input-file”, então você tem que fazê-lo em um “caminho nativo” que passe todos os arquivos (eventualmente) selecionados do usuário.

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

A parte legal é o tipo de conteúdo indefinido e o transformRequest: angular.identity que dá ao $ http a capacidade de escolher o “tipo de conteúdo” correto e gerenciar o limite necessário ao manipular dados multiparte.

Você pode usar a diretiva de upload de arquivo ng simples / leve. Suporta drag & drop, progresso de arquivos e upload de arquivos para navegadores não-HTML5 com 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); }); }]; 

Eu acabei de ter esse problema. Portanto, existem algumas abordagens. A primeira é que os novos navegadores suportam

 var formData = new FormData(); 

Siga este link para um blog com informações sobre como o suporte é limitado aos navegadores modernos, mas caso contrário, isso resolve totalmente esse problema.

Caso contrário, você poderá postar o formulário em um iframe usando o atributo de destino. Quando você postar o formulário, certifique-se de definir o destino para um iframe com sua propriedade de exibição definida como none. O alvo é o nome do iframe. (Só assim você sabe)

Eu espero que isso ajude

É mais eficiente enviar um arquivo diretamente.

A codificação base64 do Content-Type: multipart/form-data adiciona uma sobrecarga extra de 33%. Se o servidor suportar, é mais eficiente enviar os arquivos diretamente:

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

Ao enviar um POST com um object File , é importante definir 'Content-Type': undefined . O método de envio XHR detectará o object File e definirá automaticamente o tipo de conteúdo.

Para enviar vários arquivos, consulte Fazendo várias solicitações $http.post diretamente de uma lista de arquivos


Eu imaginei que deveria começar com a input type = “file”, mas depois descobri que o AngularJS não pode se ligar a isso.

O elemento não trabalha por padrão com a diretiva ng-model . Precisa de uma diretiva personalizada :

Demonstração de trabalho da diretiva “select-ng-files” que funciona com o 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}}

Eu sei que esta é uma input tardia, mas eu criei uma diretiva de upload simples. Que você pode começar a trabalhar em pouco tempo!

  

ng-simple-upload mais no Github com um exemplo usando a API da Web.

Você pode fazer o upload via $resource atribuindo dados ao atributo params de actions de resources da seguinte forma:

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

Acabei de escrever uma diretiva simples (de um curso existente) para um uploader simples em AngularJs.

(O plugin exato do uploader jQuery é https://github.com/blueimp/jQuery-File-Upload )

Um Uploader Simples usando AngularJs (com Implementação CORS)

(Embora o lado do servidor seja para PHP, você também pode simplesmente modificá-lo)

Eu gostaria de adicionar uma alternativa. Utilizando o upload de arquivo angular. Você pode encontrar uma explicação:

Você pode encontrar uma explicação detalhada aqui: https://github.com/nervgh/angular-file-upload Um exemplo: https://github.com/nervgh/angular-file-upload/tree/master/examples/simple