这是我的HTML表单:

<form name="myForm" ng-submit="">
    <input ng-model='file' type="file"/>
    <input type="submit" value='Submit'/>
</form>

我想从本地机器上传一个图像,并想读取上传文件的内容。所有这些我都想用AngularJS来做。

当我试图打印$scope的值时。文件是未定义的。


当前回答

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

一些特点:

进步 多文件 字段 旧浏览器(IE8-9)

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

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

其他回答

这里的一些答案建议使用FormData(),但不幸的是,这是一个浏览器对象,在Internet Explorer 9及以下版本中不可用。如果您需要支持这些旧浏览器,您将需要一个备份策略,例如使用<iframe>或Flash。

已经有很多Angular.js模块来执行文件上传。这两种浏览器都明确支持旧浏览器:

https://github.com/leon/angular-upload -使用iframes作为备份 https://github.com/danialfarid/ng-file-upload -使用FileAPI/Flash作为备份

还有一些其他的选择:

https://github.com/nervgh/angular-file-upload/ https://github.com/uor/angular-file https://github.com/twilson63/ngUpload https://github.com/uploadcare/angular-uploadcare

其中一个应该适合你的项目,或者可能会给你一些关于如何自己编写代码的见解。

简单的指令

Html:

<input type="file" file-upload multiple/>

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

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

在你的控制器中:

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

然后在ajax调用中:

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

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

您可以考虑使用IaaS进行文件上传,例如Uploadcare。有一个针对它的Angular包:https://github.com/uploadcare/angular-uploadcare

从技术上讲,它被实现为一个指令,提供了不同的上传选项,以及小部件中上传图像的操作:

<uploadcare-widget
  ng-model="object.image.info.uuid"
  data-public-key="YOURKEYHERE"
  data-locale="en"
  data-tabs="file url"
  data-images-only="true"
  data-path-value="true"
  data-preview-step="true"
  data-clearable="true"
  data-multiple="false"
  data-crop="400:200"
  on-upload-complete="onUCUploadComplete(info)"
  on-widget-ready="onUCWidgetReady(widget)"
  value="{{ object.image.info.cdnUrl }}"
 />

更多配置选项:https://uploadcare.com/widget/configure/

我能够通过使用下面的代码使用AngularJS上传文件:

函数ngUploadFileUpload需要传递的参数的文件是$scope。按你的问题归档。

这里的关键点是使用transformRequest:[]。这将防止$http与文件内容混淆。

       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;

        }

这应该是对@jquery-guru的答案的更新/评论,但由于我没有足够的代表,它将在这里。它修复了现在由代码生成的错误。

https://jsfiddle.net/vzhrqotw/

变化主要是:

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

To:

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

如果需要,请随意搬到更合适的地方。