使用AngularJS上传文件

Adi*_*thi 291 angularjs angularjs-fileupload

这是我的HTML表单:

<form name="myForm" ng-submit="">
    <input ng-model='file' type="file"/>
    <input type="submit" value='Submit'/>
</form>
Run Code Online (Sandbox Code Playgroud)

我想从本地计算机上传图像,并想要读取上传文件的内容.我想用AngularJS做的所有这些.

当我尝试打印$scope.file它的值时,它是未定义的.

Ano*_*oyz 342

这里提出的一些答案建议使用FormData(),但不幸的是,它是Internet Explorer 9及更低版本中不可用的浏览器对象.如果您需要支持这些旧版浏览器,则需要使用备份策略,例如使用<iframe>或Flash.

已经有很多Angular.js模块可以执行文件上传.这两个明确支持旧浏览器:

还有其他一些选择:

其中一个应该适合您的项目,或者可以让您深入了解如何自己编写代码.

  • EggHead有一个很好的视频 - https://egghead.io/lessons/angularjs-file-uploads (27认同)
  • 3岁回答.IE 9现在是2016年的DEAD. (5认同)
  • 我认为您应该更新您的答案以获得正确的解决方案,而不是指向链接.这就是堆栈溢出的方式.否则只需将其作为评论. (4认同)
  • 另一个解决方案(用于文件上传的IaaS):https://github.com/uploadcare/angular-uploadcare (3认同)
  • danialfarid/angular-file-upload重命名为ng-file-upload (2认同)
  • 至少257人和OP不同意你的看法.此外,解决方案强烈依赖于选择的库.无法理解您的评论如何改进此答案或提供帮助.也许你可能会更有建设性? (2认同)

yag*_*ger 175

最简单的是使用HTML5 API,即 FileReader

HTML非常简单:

<input type="file" id="file" name="file"/>
<button ng-click="add()">Add</button>
Run Code Online (Sandbox Code Playgroud)

在你的控制器中定义'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);
}
Run Code Online (Sandbox Code Playgroud)

浏览器兼容性

桌面浏览器

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

移动浏览器

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

注意:不推荐使用readAsBinaryString()方法,而应使用readAsArrayBuffer().

  • [FileReader.readAsBinaryString](https://developer.mozilla.org/en-US/docs/Web/API/FileReader.readAsBinaryString)自W3C截至2012年7月12日工作草案时弃用. (15认同)
  • 你不应该使用角度来访问DOM.是一个非常糟糕的做法. (13认同)
  • FileReader是标准HTML5文件API http://www.w3.org/TR/FileAPI/中的一个类.它允许您从html输入元素中指定的文件中读取数据,并在`onloadend`回调函数中处理它.您不需要任何库来使用此API,它已经在您的浏览器中(除非您使用非常旧的).希望这可以帮助. (10认同)
  • @Siderex,不在控制器中,但从指令中完成它是非常棒的.事实上,这就是指令的用途.您可以在Angular docs https://docs.angularjs.org/guide/directive中阅读相关内容 (9认同)
  • 请解释这里发生的事情!什么读者? (6认同)

Vin*_*ven 57

这是2015年的方式,没有第三方库.适用于所有最新的浏览器.

 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);
        });
    };
});
Run Code Online (Sandbox Code Playgroud)

HTML:

<input data-my-Directive type="file" name="file">
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

js小提琴(只有前端) https://jsfiddle.net/vince123/8d18tsey/31/


JQu*_*uru 38

下面是文件上传的工作示例:

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

在这个函数中调用

setFiles
Run Code Online (Sandbox Code Playgroud)

从View中将更新控制器中的文件数组

要么

您可以使用AngularJS检查jQuery文件上载

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

  • 非常有帮助,只是一个注释..这使用File API,它在IE9或以下不起作用. (4认同)

Fiz*_*han 17

您可以使用flow.js实现不错的文件和文件夹上传.

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

在这里查看演示

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

它不支持IE7,IE8,IE9,因此您最终必须使用兼容层

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


Jam*_*ruk 13

使用该onchange事件将输入文件元素传递给您的函数.

<input type="file" onchange="angular.element(this).scope().fileSelected(this)" />

因此,当用户选择文件时,您可以引用该文件而无需用户单击"添加"或"上载"按钮.

$scope.fileSelected = function (element) {
    var myFileSelected = element.files[0];
};
Run Code Online (Sandbox Code Playgroud)

  • 这不能按预期工作。这是我的工作流程: 1. 刷新页面 2. 添加新文件。** 添加的第一个文件始终未定义。** 3. 添加另一个文件。从现在开始,上传的每个文件都是我之前添加的文件。所以对于我添加的第二个文件,这将上传我添加的第一个文件(实际上失败了) (2认同)

Jav*_*aro 11

我尝试了@Anoyz(正确答案)给出的所有替代方案......最好的解决方案是https://github.com/danialfarid/angular-file-upload

一些特点:

  • 进展
  • Multifiles
  • 字段
  • 旧浏览器(IE8-9)

这对我来说很好.你只需要注意说明.

在服务器端,我使用NodeJs,Express 4和Multer中间件来管理多部分请求.


小智 9

HTML

<html>
    <head></head>

<body ng-app = "myApp">

  <form ng-controller = "myCtrl">
     <input type = "file" file-model="files" multiple/>
     <button ng-click = "uploadFile()">upload me</button>
     <li ng-repeat="file in files">{{file.name}}</li>
  </form>
Run Code Online (Sandbox Code Playgroud)

脚本

  <script src = 
     "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
  <script>
    angular.module('myApp', []).directive('fileModel', ['$parse', function ($parse) {
        return {
           restrict: 'A',
           link: function(scope, element, attrs) {
              element.bind('change', function(){
              $parse(attrs.fileModel).assign(scope,element[0].files)
                 scope.$apply();
              });
           }
        };
     }]).controller('myCtrl', ['$scope', '$http', function($scope, $http){


       $scope.uploadFile=function(){
       var fd=new FormData();
        console.log($scope.files);
        angular.forEach($scope.files,function(file){
        fd.append('file',file);
        });
       $http.post('http://localhost:1337/mediaobject/upload',fd,
           {
               transformRequest: angular.identity,
               headers: {'Content-Type': undefined}                     
            }).success(function(d)
                {
                    console.log(d);
                })         
       }
     }]);

  </script>
Run Code Online (Sandbox Code Playgroud)


geo*_*awg 9

<input type=file>默认情况下,该元素不适用于ng-model指令.它需要一个自定义指令:

return-files1一起使用的指令的工作演示ng-model

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);
      })
    }
  }
});
Run Code Online (Sandbox Code Playgroud)
<script src="//unpkg.com/angular/angular.js"></script>
  <body ng-app="app">
    <h1>AngularJS Input `type=file` Demo</h1>
    
    <input type="file" select-ng-files ng-model="fileList" multiple>
    
    <h2>Files</h2>
    <div ng-repeat="file in fileList">
      {{file.name}}
    </div>
  </body>
Run Code Online (Sandbox Code Playgroud)


$http.post来自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);
};
Run Code Online (Sandbox Code Playgroud)

使用File对象发送POST时,设置很重要'Content-Type': undefined.然后,XHR send方法将检测File对象并自动设置内容类型.


Ash*_*her 7

轻松掌握指令

HTML:

<input type="file" file-upload multiple/>
Run Code Online (Sandbox Code Playgroud)

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<files.length;i++) {
                //emit event upward
                scope.$emit("fileSelected", { file: files[i] });
            }                                       
        });
    }
};
Run Code Online (Sandbox Code Playgroud)

在指令中,我们确保创建一个新范围,然后监听对文件输入元素所做的更改.检测到更改时,将文件对象作为参数向所有祖先范围(向上)发出事件.

在你的控制器中:

$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);
    });
});
Run Code Online (Sandbox Code Playgroud)

然后在你的ajax调用中:

data: { model: $scope.model, files: $scope.files }
Run Code Online (Sandbox Code Playgroud)

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


Moh*_*deh 7

我认为这是角度文件上传:

NG-文件上传

用于上传文件的轻量级Angular JS指令.

这是DEMO页面.功能

  • 支持上传进度,正在进行取消/中止上传,文件拖放(html5),目录拖放(webkit),CORS,PUT(html5)/ POST方法,文件类型和大小验证,显示所选图像的预览/音频/视频.
  • 使用Flash polyfill FileAPI跨浏览器文件上载和FileReader(HTML5和非HTML5).在上载文件之前允许客户端验证/修改
  • 使用Upload.http()直接上传到数据库服务CouchDB,imgur等...文件的内容类型.这将启用角度http POST/PUT请求的进度事件.
  • 单独的填充程序文件,FileAPI文件是根据需要加载的非HTML5代码,这意味着如果您只需要HTML5支持,则无需额外的加载/代码.
  • 轻量级使用常规$ http上传(使用非HTML5浏览器的垫片),因此所有角度$ http功能都可用

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


bar*_*acı 6

您的文件和json数据同时上传.

// 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
Run Code Online (Sandbox Code Playgroud)