我想从AngularJS到node.js服务器做一个简单的多部分表单帖子, 表单应包含一个部分中的JSON对象和另一部分中的图像, (我目前只发布带有$ resource的JSON对象)
我想我应该从输入类型="文件"开始,但后来发现AngularJS无法绑定到那个..
我能找到的所有例子都是用于包装用于拖放的jQuery插件。下降。我想简单上传一个文件。
我是AngularJS的新手,并且在编写我自己的指令时感到不舒服。
答案 0 :(得分:182)
一个真正有效的解决方案,没有其他依赖关系而不是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中为选择正确的“内容类型”提供了能力并管理处理多部分数据时所需的边界。
答案 1 :(得分:42)
您可以使用简单/轻量级ng-file-upload指令。 它支持使用FileAPI flash shim的非HTML5浏览器的拖放,文件进度和文件上传
<div ng-controller="MyCtrl">
<input type="file" ngf-select="onFileSelect($files)" multiple>
</div>
JS:
//inject angular file upload directive.
angular.module('myApp', ['ngFileUpload']);
var MyCtrl = [ '$scope', 'Upload', function($scope, Upload) {
$scope.onFileSelect = function($files) {
Upload.upload({
url: 'my/upload/url',
file: $files,
}).progress(function(e) {
}).then(function(data, status, headers, config) {
// file is uploaded successfully
console.log(data);
});
}];
答案 2 :(得分:7)
Content-Type: multipart/form-data
的{{3}}会增加额外33%的开销。如果服务器支持它,则更有效地直接发送文件:
$scope.upload = function(url, file) {
var config = { headers: { 'Content-Type': undefined },
transformResponse: angular.identity
};
return $http.post(url, file, config);
};
发送带有base64 encoding的POST时,设置'Content-Type': undefined
非常重要。然后,File object会检测XHR send method并自动设置内容类型。
要发送多个文件,请参阅File object
我想我应该从input type =“file”开始,但后来发现AngularJS无法绑定到那个..
默认情况下,<input type=file>
元素不会与Doing Multiple $http.post
Requests Directly from a FileList一起使用。它需要ng-model directive:
ng-model
custom directive
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);
})
}
}
});
<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="fileArray" multiple>
<h2>Files</h2>
<div ng-repeat="file in fileArray">
{{file.name}}
</div>
</body>
内容类型为
$http.post
的multipart/form-data
如果必须发送multipart/form-data
:
<form role="form" enctype="multipart/form-data" name="myForm">
<input type="text" ng-model="fdata.UserName">
<input type="text" ng-model="fdata.FirstName">
<input type="file" select-ng-files ng-model="filesArray" multiple>
<button type="submit" ng-click="upload()">save</button>
</form>
$scope.upload = function() {
var fd = new FormData();
fd.append("data", angular.toJson($scope.fdata));
for (i=0; i<$scope.filesArray.length; i++) {
fd.append("file"+i, $scope.filesArray[i]);
};
var config = { headers: {'Content-Type': undefined},
transformRequest: angular.identity
}
return $http.post(url, fd, config);
};
使用1发送POST时,设置'Content-Type': undefined
非常重要。然后,FormData API将检测FormData
对象,并使用XHR send method自动将内容类型标头设置为multipart/form-data。
答案 3 :(得分:5)
我刚遇到这个问题。所以有一些方法。首先是新浏览器支持
var formData = new FormData();
Follow this link to a blog with info about支持仅限于现代浏览器,但完全解决了这个问题。
否则,您可以使用target属性将表单发布到iframe。 发布表单时,请确保将目标设置为iframe,并将其display属性设置为none。 目标是iframe的名称。 (只是你知道。)
我希望这会有所帮助
答案 4 :(得分:2)
我知道这是一个迟到的条目,但我创建了一个简单的上传指令。您可以立即开始工作!
<input type="file" multiple ng-simple-upload web-api-url="/api/post"
callback-fn="myCallback" />
ng-simple-upload更多关于Github的例子,使用Web API。
答案 5 :(得分:1)
我刚刚在AngularJs中为一个简单的上传器编写了一个简单的指令(来自现有的一个)。
(确切的jQuery上传器插件是https://github.com/blueimp/jQuery-File-Upload)
A Simple Uploader using AngularJs (with CORS Implementation)
(虽然服务器端用于PHP,但您也可以简单地更改它节点)
答案 6 :(得分:1)
您可以通过将数据分配给资源$resource
的params属性来通过actions
上传,如下所示:
$scope.uploadFile = function(files) {
var fdata = new FormData();
fdata.append("file", files[0]);
$resource('api/post/:id', { id: "@id" }, {
postWithFile: {
method: "POST",
data: fdata,
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
}
}).postWithFile(fdata).$promise.then(function(response){
//successful
},function(error){
//error
});
};