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 将文件上传到 Google Drive
AngularJS:使用 $resource 上传文件(解决方案)