AngularJS 使用 ng-upload 上传图片

Posted

技术标签:

【中文标题】AngularJS 使用 ng-upload 上传图片【英文标题】:AngularJS Uploading An Image With 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。

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

【问题讨论】:

访问这里通过 Angular 获取简单的图片上传教程。它真的帮助了我tutorialspoint.com/angularjs/angularjs_upload_file.htm 注意这个问题与ng-upload 库有关。不是ng-file-upload 库。 【参考方案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 ****************

    imgwidth: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>

【讨论】:

以上是关于AngularJS 使用 ng-upload 上传图片的主要内容,如果未能解决你的问题,请参考以下文章

Angularjs - 使用 php 上传文件

如何使用 AngularJS 将文件上传到 Google Drive

AngularJS:使用 $resource 上传文件(解决方案)

使用 AngularJS 上传文件

使用 AngularJS 和 SpringMVC 进行多部分文件上传

如何在angularjs中使用ng-file上传裁剪和上传图像