【问题标题】:AngularJS Uploading An Image With ng-uploadAngularJS 使用 ng-upload 上传图片
【发布时间】:2013-06-17 11:55:18
【问题描述】:

我正在尝试使用 ng-upload 在 AngularJS 中上传文件,但我遇到了问题。我的 html 看起来像这样:

<div class="create-article" ng-controller="PostCreateCtrl">
        <form ng-upload method="post" enctype="multipart/form-data" action="/write" >
            <fieldset>
                <label>Category</label>
                <select name="category_id" class="">
                    <option value="0">Select A Category</option>
                    <?php foreach($categories as $category): ?>
                        <option value="<?= $category -> category_id; ?>"><?= $category -> category_name; ?></option>
                    <?php endforeach; ?>
                </select>

                <label>Title</label>
                <input type="text" class="title span5" name="post_title"
                       placeholder="A catchy title here..."
                       value="<?= $post -> post_title; ?>" />

                <label>Attach Image</label>
                <input type="file" name="post_image" />

                 <a href='javascript:void(0)'  class="upload-submit: uploadPostImage(contents, completed)" >Crop Image</a>

                <label>Body</label>
                <div id="container">
                <textarea id="mytextarea" wrap="off" name="post_content" class="span7" placeholder="Content..."><?= $post -> post_content; ?></textarea>
                </div>
                <div style='clear:both;'></div>
                <label>Preview</label>
                <div id='textarea-preview'></div>

            </fieldset>
            <div class="span7" style="margin: 0;">
                <input type="submit" class="btn btn-success" value="Create Post" />
            <input type="submit" class="btn btn-warning pull-right draft" value="Save as Draft" />
            </div>

        </form>
    </div>

而我的 js 控制器是这样的:

ClabborApp.controller("PostCreateCtrl", ['$scope', 'PostModel',
function($scope, PostModel) {

    $scope.uploadPostImage = function(contents, completed) {
        console.log(completed);
        alert(contents);
    }

}]);

我面临的问题是当裁剪图像被点击并执行uploadPostImage时,它会上传整个表单。不是想要的行为,但我可以让它工作。最大的问题是在 js 中,函数 uploadPostImage 'contents' 参数始终未定义,即使 'completed' 参数返回为 true。

我们的目标是只上传一张图片进行裁剪。在这个过程中我做错了什么?

【问题讨论】:

标签: javascript angularjs angularjs-http angularjs-fileupload


【解决方案1】:

几乎没有关于上传文件的 Angular 文档。许多解决方案需要自定义指令其他依赖项(primis中的jquery ...只是为了上传文件...)。经过多次尝试后,我发现只有 angularjs(在 v.1.0.6 上测试)

html

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

Angularjs (1.0.6) 不支持“输入文件”标签上的 ng-model ,因此您必须以“本机方式”来传递所有(最终)选定的文件来自用户。

控制器

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

};

很酷的部分是 undefined 内容类型和 transformRequest: angular.identity 让 $http 能够选择正确的“内容类型”并管理处理多部分数据时所需的边界。

【讨论】:

  • 我可以在这里连同 fd 一起发送一些 JSON 数据吗?在 fd 我总是得到空值,但文件 [0] 在那里。有什么问题
  • 您使用的是此处发布的代码吗?无论如何关于发送 json 数据,实际上还不知道:p 最好在这个主题上发布一个新答案。
  • 在我开发php之前已经很久了,无论如何这与使用文件“文件”构建表单然后在“uploadUrl”处使用POST提交的效果相同。
  • @StenMuchow 遗憾的是,'file' 似乎还不支持与 ng-change github.com/angular/angular.js/issues/1375的绑定
  • 答案是针对 AngularJS 1.0.6 给出的。 Angular 1.2.26 或 1.3 现在有更好的东西吗?文档仍然没有提供更好的解决方法。
【解决方案2】:

你可以试试ng-file-upload angularjs 插件(而不是ng-upload)。

设置和处理 angularjs 细节相当容易。它还支持进度、取消、拖放,并且是跨浏览器的。

html

<!-- Note: MUST BE PLACED BEFORE angular.js-->
<script src="ng-file-upload-shim.min.js"></script> 
<script src="angular.min.js"></script>
<script src="ng-file-upload.min.js"></script> 

<div ng-controller="MyCtrl">
  <input type="file" ngf-select="onFileSelect($files)" multiple>
</div>

JS:

//inject angular file upload directives and service.
angular.module('myApp', ['ngFileUpload']);

var MyCtrl = [ '$scope', '$upload', function($scope, $upload) {
  $scope.onFileSelect = function($files) {
    //$files: an array of files selected, each file has name, size, and type.
    for (var i = 0; i < $files.length; i++) {
      var file = $files[i];
      $scope.upload = $upload.upload({
        url: 'server/upload/url', //upload.php script, node.js route, or servlet url
        data: {myObj: $scope.myModelObj},
        file: file,
      }).progress(function(evt) {
        console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
      }).then(function(response) {
        var data = response.data;
        // file is uploaded successfully
        console.log(data);
      });
    }
  };
}];

【讨论】:

    【解决方案3】:

    在我的情况下,上述方法适用于 php,但是当我尝试在 node.js 中使用这些方法上传文件时,我遇到了一些问题。 所以不要使用 $http({..,..,...}) 使用普通的 jquery ajax。

    对于选择文件使用这个

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

    在控制器中

    $scope.uploadFile = function(element) {   
    var data = new FormData();
    data.append('file', $(element)[0].files[0]);
    jQuery.ajax({
          url: 'brand/upload',
          type:'post',
          data: data,
          contentType: false,
          processData: false,
          success: function(response) {
          console.log(response);
          },
          error: function(jqXHR, textStatus, errorMessage) {
          alert('Error uploading: ' + errorMessage);
          }
     });   
    };
    

    【讨论】:

    • 这个答案使用 jQuery 而不是 ng-file-upload 或 AngularJS $http 服务。
    • @Tek Raj Pant 你有什么想法吗?我如何在上面的 html 部分给出默认图像。我想默认设置一个图像,这样我的按钮就可以安全地保存工作,而无需调用或不调用 onchange
    【解决方案4】:
            var app = angular.module('plunkr', [])
        app.controller('UploadController', function($scope, fileReader) {
            $scope.imageSrc = "";
    
            $scope.$on("fileProgress", function(e, progress) {
            $scope.progress = progress.loaded / progress.total;
            });
        });
    
    
    
    
        app.directive("ngFileSelect", function(fileReader, $timeout) {
            return {
            scope: {
                ngModel: '='
            },
            link: function($scope, el) {
                function getFile(file) {
                fileReader.readAsDataUrl(file, $scope)
                    .then(function(result) {
                    $timeout(function() {
                        $scope.ngModel = result;
                    });
                    });
                }
    
                el.bind("change", function(e) {
                var file = (e.srcElement || e.target).files[0];
                getFile(file);
                });
            }
            };
        });
    
        app.factory("fileReader", function($q, $log) {
        var onLoad = function(reader, deferred, scope) {
            return function() {
            scope.$apply(function() {
                deferred.resolve(reader.result);
            });
            };
        };
    
        var onError = function(reader, deferred, scope) {
            return function() {
            scope.$apply(function() {
                deferred.reject(reader.result);
            });
            };
        };
    
        var onProgress = function(reader, scope) {
            return function(event) {
            scope.$broadcast("fileProgress", {
                total: event.total,
                loaded: event.loaded
            });
            };
        };
    
        var getReader = function(deferred, scope) {
            var reader = new FileReader();
            reader.onload = onLoad(reader, deferred, scope);
            reader.onerror = onError(reader, deferred, scope);
            reader.onprogress = onProgress(reader, scope);
            return reader;
        };
    
        var readAsDataURL = function(file, scope) {
            var deferred = $q.defer();
    
            var reader = getReader(deferred, scope);
            reader.readAsDataURL(file);
    
            return deferred.promise;
        };
    
        return {
            readAsDataUrl: readAsDataURL
        };
        });
    
    
    
        *************** CSS ****************
    
        img{width:200px; height:200px;}
    
        ************** HTML ****************
    
        <div ng-app="app">
        <div ng-controller="UploadController ">
            <form>
            <input type="file" ng-file-select="onFileSelect($files)" ng-model="imageSrc">
                    <input type="file" ng-file-select="onFileSelect($files)" ng-model="imageSrc2">
            <!--  <input type="file" ng-file-select="onFileSelect($files)" multiple> -->
            </form>
    
            <img ng-src="{{imageSrc}}" />
        <img ng-src="{{imageSrc2}}" />
    
        </div>
        </div>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-11
      • 2017-05-01
      • 2016-08-24
      • 1970-01-01
      • 2017-01-26
      • 2015-10-02
      • 2019-05-19
      • 2016-11-15
      相关资源
      最近更新 更多