Upload de arquivo usando o AngularJS

Aqui está o meu formulário HTML:

    

Quero fazer upload de uma imagem da máquina local e quero ler o conteúdo do arquivo enviado. Tudo isso eu quero fazer usando o AngularJS.

Quando tento imprimir o valor de $scope.file ele é indefinido.

Algumas das respostas aqui propõem o uso de FormData() , mas infelizmente esse é um object de navegador não disponível no Internet Explorer 9 e abaixo. Se você precisar dar suporte a esses navegadores mais antigos, precisará de uma estratégia de backup, como o uso de ou Flash.

Já existem muitos módulos do Angular.js para realizar o upload de arquivos. Estes dois têm suporte explícito para navegadores mais antigos:

E algumas outras opções:

Um deles deve se adequar ao seu projeto ou fornecer algumas dicas sobre como codificá-lo.

O mais fácil é usar a API HTML5, ou seja, FileReader

O HTML é bem direto:

   

Em seu controlador, defina o método ‘add’:

 $scope.add = function() { var f = document.getElementById('file').files[0], r = new FileReader(); r.onloadend = function(e) { var data = e.target.result; //send your binary data via $http or $resource or do anything else with it } r.readAsBinaryString(f); } 

Compatibilidade do Navegador

Navegadores de desktop

Firefox (Gecko) 3.6 (1.9.2), Chrome 7, Internet Explorer * 10, Opera * 12.02, Safari 6.0.2

Navegadores móveis

Firefox (Gecko) 32, Chrome 3, Internet Explorer * 10, Opera * 11.5, Safari 6.1

Nota: o método readAsBinaryString () está obsoleto e readAsArrayBuffer () deve ser usado em seu lugar.

Este é o caminho de 2015, sem bibliotecas de terceiros. Funciona em todos os navegadores mais recentes.

  app.directive('myDirective', function (httpPostFactory) { return { restrict: 'A', scope: true, link: function (scope, element, attr) { element.bind('change', function () { var formData = new FormData(); formData.append('file', element[0].files[0]); httpPostFactory('upload_image.php', formData, function (callback) { // recieve image name to use in a ng-src console.log(callback); }); }); } }; }); app.factory('httpPostFactory', function ($http) { return function (file, data, callback) { $http({ url: file, method: "POST", data: data, headers: {'Content-Type': undefined} }).success(function (response) { callback(response); }); }; }); 

HTML:

  

PHP:

 if (isset($_FILES['file']) && $_FILES['file']['error'] == 0) { // uploads image in the folder images $temp = explode(".", $_FILES["file"]["name"]); $newfilename = substr(md5(time()), 0, 10) . '.' . end($temp); move_uploaded_file($_FILES['file']['tmp_name'], 'images/' . $newfilename); // give callback to your angular code with the image src name echo json_encode($newfilename); } 

js violino (apenas front-end) https://jsfiddle.net/vince123/8d18tsey/31/

Abaixo está um exemplo prático de upload de arquivo:

http://jsfiddle.net/vishalvasani/4hqVu/

Nesta function chamada

 setFiles 

From View, que atualizará a matriz de arquivos no controlador

ou

Você pode verificar o upload do arquivo jQuery usando o AngularJS

http://blueimp.github.io/jQuery-File-Upload/angularjs.html

Você pode conseguir um bom upload de arquivos e pastas usando flow.js.

https://github.com/flowjs/ng-flow

Confira uma demonstração aqui

http://flowjs.github.io/ng-flow/

Ele não suporta IE7, IE8, IE9, então você terá que usar uma camada de compatibilidade

https://github.com/flowjs/fusty-flow.js

Eu tentei todas as alternativas que @Anoyz (resposta correta) dá … e a melhor solução é https://github.com/danialfarid/angular-file-upload

Algumas funcionalidades:

  • Progresso
  • Multifiles
  • Campos
  • Navegadores antigos (IE8-9)

Funciona bem para mim. Você só precisa prestar atenção às instruções.

No lado do servidor, eu uso o middleware NodeJs, Express 4 e Multer para gerenciar solicitações de várias partes.

HTML

    
  • {{file.name}}
  • Scripts

        

    Use o evento onchange para passar o elemento do arquivo de input para sua function.

    Assim, quando um usuário seleciona um arquivo, você tem uma referência a ele sem que o usuário precise clicar em um botão “Adicionar” ou “Carregar”.

     $scope.fileSelected = function (element) { var myFileSelected = element.files[0]; }; 

    Fácil com uma diretiva

    Html:

      

    JS:

     app.directive('fileUpload', function () { return { scope: true, //create a new scope link: function (scope, el, attrs) { el.bind('change', function (event) { var files = event.target.files; //iterate files since 'multiple' may be specified on the element for (var i = 0;i 

    Na diretiva, garantimos que um novo escopo seja criado e, em seguida, escute as alterações feitas no elemento de input do arquivo. Quando são detectadas alterações com a emissão de um evento para todos os escopos de ancestral (para cima) com o object de arquivo como um parâmetro.

    No seu controlador:

     $scope.files = []; //listen for the file selected event $scope.$on("fileSelected", function (event, args) { $scope.$apply(function () { //add the file object to the scope's files collection $scope.files.push(args.file); }); }); 

    Então, na sua chamada ajax:

     data: { model: $scope.model, files: $scope.files } 

    http://shazwazza.com/post/uploading-files-and-json-data-in-the-same-request-with-angular-js/

    Eu acho que este é o upload do arquivo angular:

    ng-file-upload

    Diretiva JS angular leve para carregar arquivos.

    Aqui está a página DEMO .

    • Suporta progresso de upload, cancelamento / cancelamento de upload em andamento, arrastar e soltar arquivos (html5), arrastar e soltar diretórios (webkit), CORS, PUT (html5) / methods POST, validação do tipo e tamanho do arquivo, visualização de exibição das imagens selecionadas / áudio / vídeos.
    • Upload de arquivos entre navegadores e FileReader (HTML5 e não-HTML5) com o FileAPI do polyfill do Flash. Permite a validação / modificação do lado do cliente antes de fazer o upload do arquivo
    • Upload direto para serviços de database CouchDB, imgur, etc … com o tipo de conteúdo do arquivo usando Upload.http (). Isso permite o evento de progresso para solicitações HTTP POST / PUT angulares.
    • Arquivo shim separado, arquivos FileAPI são carregados sob demanda para código não-HTML5, o que significa que não há carga / código extra se você precisar apenas de suporte HTML5.
    • Leve usando $ http regular para carregar (com calço para navegadores não-HTML5) para que todos os resources $ http angulares estejam disponíveis

    https://github.com/danialfarid/ng-file-upload

    Seu arquivo e dados do json são enviados ao mesmo tempo.

     // FIRST SOLUTION var _post = function (file, jsonData) { $http({ url: your url, method: "POST", headers: { 'Content-Type': undefined }, transformRequest: function (data) { var formData = new FormData(); formData.append("model", angular.toJson(data.model)); formData.append("file", data.files); return formData; }, data: { model: jsonData, files: file } }).then(function (response) { ; }); } // END OF FIRST SOLUTION // SECOND SOLUTION // İf you can add plural file and İf above code give an error. // You can try following code var _post = function (file, jsonData) { $http({ url: your url, method: "POST", headers: { 'Content-Type': undefined }, transformRequest: function (data) { var formData = new FormData(); formData.append("model", angular.toJson(data.model)); for (var i = 0; i < data.files.length; i++) { // add each file to // the form data and iteratively name them formData.append("file" + i, data.files[i]); } return formData; }, data: { model: jsonData, files: file } }).then(function (response) { ; }); } // END OF SECOND SOLUTION 

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

    Demonstração de trabalho da diretiva de return-files de return-files que funciona com ng-model 1

     angular.module("app",[]); angular.module("app").directive("returnFiles", 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}}

    Você pode usar um object FormData seguro e rápido:

     // Store the file object when input field is changed $scope.contentChanged = function(event){ if (!event.files.length) return null; $scope.content = new FormData(); $scope.content.append('fileUpload', event.files[0]); $scope.$apply(); } // Upload the file over HTTP $scope.upload = function(){ $http({ method: 'POST', url: '/remote/url', headers: {'Content-Type': undefined }, data: $scope.content, }).success(function(response) { // Uploading complete console.log('Request finished', response); }); } 

    http://jsfiddle.net/vishalvasani/4hqVu/ funciona bem em chrome e IE (se você atualizar CSS um pouco em background-image). Isso é usado para atualizar a barra de progresso:

      scope.progress = Math.round(evt.loaded * 100 / evt.total) 

    mas nos dados [percentuais] do FireFox, o angular não é atualizado no DOM com êxito, embora os arquivos estejam sendo carregados com êxito.

    Você pode considerar IaaS para upload de arquivos, como o Uploadcare . Existe um pacote Angular para isso: https://github.com/uploadcare/angular-uploadcare

    Tecnicamente, ele é implementado como uma diretiva, oferecendo diferentes opções de upload e manipulações para imagens carregadas no widget:

      

    Mais opções de configuração para brincar: https://uploadcare.com/widget/configure/

    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.

    Isso deve ser uma atualização / comentário para a resposta do @jquery-guru, mas como eu não tenho o suficiente, ele irá para aqui. Ele corrige os erros que agora são gerados pelo código.

    https://jsfiddle.net/vzhrqotw/

    A mudança é basicamente:

     FileUploadCtrl.$inject = ['$scope'] function FileUploadCtrl(scope) { 

    Para:

     app.controller('FileUploadCtrl', function($scope) { 

    Sinta-se à vontade para se deslocar para um local mais apropriado, se desejar.

    Eu li todo o segmento e a solução de API HTML5 parecia a melhor. Mas isso muda meus arquivos binários, corrompendo-os de uma maneira que eu não investiguei. A solução que funcionou perfeitamente para mim foi:

    HTML:

       

    JS:

     msds_update = function() { var f = document.getElementById('msds').files[0], r = new FileReader(); r.onloadend = function(e) { var data = e.target.result; console.log(data); var fd = new FormData(); fd.append('file', data); fd.append('file_name', f.name); $http.post('server_handler.php', fd, { transformRequest: angular.identity, headers: {'Content-Type': undefined} }) .success(function(){ console.log('success'); }) .error(function(){ console.log('error'); }); }; r.readAsDataURL(f); } 

    Lado do servidor (PHP):

     $file_content = $_POST['file']; $file_content = substr($file_content, strlen('data:text/plain;base64,')); $file_content = base64_decode($file_content); 
     

    No controlador angularjs

     $scope.submit_import_csv = function(){ var formData = new FormData(document.getElementById("csv_file_form")); console.log(formData); $.ajax({ url: "import", type: 'POST', data: formData, mimeType:"multipart/form-data", contentType: false, cache: false, processData:false, success: function(result, textStatus, jqXHR) { console.log(result); } }); return false; } 

    Eu posso fazer upload de arquivos usando o AngularJS usando o código abaixo:

    O file para o argumento que precisa ser passado para a function ngUploadFileUpload é $scope.file conforme sua pergunta.

    O ponto chave aqui é usar transformRequest: [] . Isso impedirá que o $ http interfira no conteúdo do arquivo.

      function getFileBuffer(file) { var deferred = new $q.defer(); var reader = new FileReader(); reader.onloadend = function (e) { deferred.resolve(e.target.result); } reader.onerror = function (e) { deferred.reject(e.target.error); } reader.readAsArrayBuffer(file); return deferred.promise; } function ngUploadFileUpload(endPointUrl, file) { var deferred = new $q.defer(); getFileBuffer(file).then(function (arrayBuffer) { $http({ method: 'POST', url: endPointUrl, headers: { "accept": "application/json;odata=verbose", 'X-RequestDigest': spContext.securityValidation, "content-length": arrayBuffer.byteLength }, data: arrayBuffer, transformRequest: [] }).then(function (data) { deferred.resolve(data); }, function (error) { deferred.reject(error); console.error("Error", error) }); }, function (error) { console.error("Error", error) }); return deferred.promise; } 

    A resposta aceita acima não é compatível com o navegador. Se alguém tiver problema de compatibilidade, tente isso.

    Violino

    Ver código

      

    {{data}}

    Código controlador

     var myApp = angular.module('myApp',[]); function MyCtrl($scope) { $scope.data = 'none'; $scope.add = function(){ var f = document.getElementById('file').files[0], r = new FileReader(); r.onloadend = function(e){ var binary = ""; var bytes = new Uint8Array(e.target.result); var length = bytes.byteLength; for (var i = 0; i < length; i++) { binary += String.fromCharCode(bytes[i]); } $scope.data = (binary).toString(); alert($scope.data); } r.readAsArrayBuffer(f); } } 

    HTML

      

    adicione o método ‘profileimage ()’ ao seu controlador

      $scope.profileimage = function(selectimage) { console.log(selectimage.files[0]); var selectfile=selectimage.files[0]; r = new FileReader(); r.onloadend = function (e) { debugger; var data = e.target.result; } r.readAsBinaryString(selectfile); } 

    em palavras simples

    em HTML – adicione apenas o código abaixo

      

    no controlador – Essa function é chamada quando você clica em “carregar botão do arquivo” . ele fará o upload do arquivo. você pode consolá-lo.

     $scope.uploadedFile = function(element) { $scope.$apply(function($scope) { $scope.files = element.files; }); } 

    adicione mais nos controladores – abaixo o código adiciona na function. Esta function é chamada quando você clica no botão que é usado “acertando a API (POST)” . ele enviará o arquivo (que enviou) e os dados do formulário para o back-end.

     var url = httpURL + "/reporttojson" var files=$scope.files; for ( var i = 0; i < files.length; i++) { var fd = new FormData(); angular.forEach(files,function(file){ fd.append('file',file); }); var data ={ msg : message, sub : sub, sendMail: sendMail, selectUsersAcknowledge:false }; fd.append("data", JSON.stringify(data)); $http.post(url, fd, { withCredentials : false, headers : { 'Content-Type' : undefined }, transformRequest : angular.identity }).success(function(data) { toastr.success("Notification sent successfully","",{timeOut: 2000}); $scope.removereport() $timeout(function() { location.reload(); }, 1000); }).error(function(data) { toastr.success("Error in Sending Notification","",{timeOut: 2000}); $scope.removereport() }); } 

    neste caso .. eu adicionei abaixo o código como dados do formulário

     var data ={ msg : message, sub : sub, sendMail: sendMail, selectUsersAcknowledge:false }; 

    Nós usamos HTML, CSS e AngularJS. O exemplo a seguir mostra como fazer o upload do arquivo usando o AngularJS.

          

    Exemplo de trabalho usando diretiva simples ( ng-file-model ):

     .directive("ngFileModel", [function () { return { $scope: { ngFileModel: "=" }, link: function ($scope:any, element, attributes) { element.bind("change", function (changeEvent:any) { var reader = new FileReader(); reader.onload = function (loadEvent) { $scope.$apply(function () { $scope.ngFileModel = { lastModified: changeEvent.target.files[0].lastModified, lastModifiedDate: changeEvent.target.files[0].lastModifiedDate, name: changeEvent.target.files[0].name, size: changeEvent.target.files[0].size, type: changeEvent.target.files[0].type, data: changeEvent.target.files[0] }; }); } reader.readAsDataURL(changeEvent.target.files[0]); }); } } }]) 

    e use FormData para fazer o upload do arquivo em sua function.

     var formData = new FormData(); formData.append("document", $scope.ngFileModel.data) formData.append("user_id", $scope.userId) 

    todos os créditos vão para https://github.com/mistralworks/ng-file-model

    Eu enfrentei um pequeno problema que você pode verificar aqui: https://github.com/mistralworks/ng-file-model/issues/7

    Finalmente, aqui está um repository bifurcado: https://github.com/okasha93/ng-file-model/blob/patch-1/ng-file-model.js

    O código ajudará a inserir o arquivo

      

    Select Picture

    insert.js

     var app = angular.module('myApp',[]); app.service('uploadFile', ['$http','$window', function ($http,$window) { this.uploadFiletoServer = function(file,uploadUrl){ var fd = new FormData(); fd.append('file', file); $http.post(uploadUrl, fd, { transformRequest: angular.identity, headers: {'Content-Type': undefined} }) .success(function(data){ alert("insert successfull"); $window.location.href = ' ';//your window location }) .error(function(){ alert("Error"); }); } }]); app.controller('insert_Ctrl', ['$scope', 'uploadFile', function($scope, uploadFile){ $scope.uploadFile = function() { $scope.myFile = $scope.files[0]; var file = $scope.myFile; var url = "save_data.php"; uploadFile.uploadFiletoServer(file,url); }; $scope.uploadedFile = function(element) { var reader = new FileReader(); reader.onload = function(event) { $scope.$apply(function($scope) { $scope.files = element.files; $scope.src = event.target.result }); } reader.readAsDataURL(element.files[0]); } }]); 

    save_data.php

      

    isso funciona

    file.html

          

    controller.js

      var app = angular.module('app', []); app.service('fileUpload', ['$http', function ($http) { this.uploadFileToUrl = function(file, uploadUrl){ var fd = new FormData(); fd.append('file', file); $http.post(uploadUrl, fd, { transformRequest: angular.identity, headers: {'Content-Type': undefined} }).success(function(res){ console.log(res); }).error(function(error){ console.log(error); }); } }]); app.controller('fileCtrl', ['$scope', 'fileUpload', function($scope, fileUpload){ $scope.uploadFile = function(){ var file = $scope.myFile; console.log('file is ' ); console.dir(file); var uploadUrl = "/fileUpload.php"; // upload url stands for api endpoint to handle upload to directory fileUpload.uploadFileToUrl(file, uploadUrl); }; }]);  

    fileupload.php

       

    FAZER UPLOAD DE ARQUIVOS

      $scope.uploadResume = function () { var f = document.getElementById('resume').files[0]; $scope.selectedResumeName = f.name; $scope.selectedResumeType = f.type; r = new FileReader(); r.onloadend = function (e) { $scope.data = e.target.result; } r.readAsDataURL(f); }; 

    BAIXAR ARQUIVOS:

       download resume var app = angular.module("myApp", []); app.config(['$compileProvider', function ($compileProvider) { $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|local|data|chrome-extension):/); $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|local|data|chrome-extension):/); }]); 
     app.directive('ngUpload', function () { return { restrict: 'A', link: function (scope, element, attrs) { var options = {}; options.enableControls = attrs['uploadOptionsEnableControls']; // get scope function to execute on successful form upload if (attrs['ngUpload']) { element.attr("target", "upload_iframe"); element.attr("method", "post"); // Append a timestamp field to the url to prevent browser caching results element.attr("action", element.attr("action") + "?_t=" + new Date().getTime()); element.attr("enctype", "multipart/form-data"); element.attr("encoding", "multipart/form-data"); // Retrieve the callback function var fn = attrs['ngUpload'].split('(')[0]; var callbackFn = scope.$eval(fn); if (callbackFn == null || callbackFn == undefined || !angular.isFunction(callbackFn)) { var message = "The expression on the ngUpload directive does not point to a valid function."; // console.error(message); throw message + "\n"; } // Helper function to create new i frame for each form submission var addNewDisposableIframe = function (submitControl) { // create a new iframe var iframe = $(""); // attach function to load event of the iframe iframe.bind('load', function () { // get content - requires jQuery var content = iframe.contents().find('body').text(); // execute the upload response function in the active scope scope.$apply(function () { callbackFn(content, content !== "" /* upload completed */); }); // remove iframe if (content != "") // Fixes a bug in Google Chrome that dispose the iframe before content is ready. setTimeout(function () { iframe.remove(); }, 250); submitControl.attr('disabled', null); submitControl.attr('title', 'Click to start upload.'); }); // add the new iframe to application element.parent().append(iframe); }; // 1) get the upload submit control(s) on the form (submitters must be decorated with the 'ng-upload-submit' class) // 2) attach a handler to the controls' click event $('.upload-submit', element).click( function () { addNewDisposableIframe($(this) /* pass the submit control */); scope.$apply(function () { callbackFn("Please wait...", false /* upload not completed */); }); var enabled = true; if (options.enableControls === null || options.enableControls === undefined || options.enableControls.length >= 0) { // disable the submit control on click $(this).attr('disabled', 'disabled'); enabled = false; } $(this).attr('title', (enabled ? '[ENABLED]: ' : '[DISABLED]: ') + 'Uploading, please wait...'); // submit the form $(element).submit(); } ).attr('title', 'Click to start upload.'); } else alert("No callback function found on the ngUpload directive."); } }; }); 
    @RequestMapping(value = "/uploadHelpFile", method = RequestMethod.POST) public @ResponseBody String uploadHelpFile(@RequestParam(value = "file") CommonsMultipartFile[] file,@RequestParam(value = "fileName") String fileName,@RequestParam(value = "helpFileType") String helpFileType,@RequestParam(value = "helpFileName") String helpFileName) { }