我正在使用AngularJS与RESTful
Web服务进行交互,$resource
用于提取公开的各种实体。其中一些实体是图像,因此我需要能够使用“对象”
的save
动作$resource
在同一请求中发送二进制数据和文本字段。
如何$resource
在单个POST
请求中使用AngularJS的服务发送数据并将图像上传到宁静的Web服务?
我进行了无数次搜索,尽管可能会错过它,但找不到该问题的解决方案:使用$ resource操作上传文件。
让我们举个例子:RESTful服务允许我们通过向/images/
端点发出请求来访问图像。每个Image
都有标题,描述和指向图像文件的路径。使用RESTful服务,我们可以获得所有这些(GET /images/
),单个(GET /images/1
)或添加一个(POST/images
)。Angular允许我们使用$resource服务轻松完成此任务,但不允许开箱即用地进行文件上传(这是第三项操作所必需的)(而且他们似乎并没有计划随时支持它)很快)。如果无法处理文件上传,那么我们将如何使用非常方便的$resource服务呢?事实证明这很容易!
我们将使用数据绑定,因为它是AngularJS的出色功能之一。我们有以下HTML表单:
<form class="form" name="form" novalidate ng-submit="submit()">
<div class="form-group">
<input class="form-control" ng-model="newImage.title" placeholder="Title" required>
</div>
<div class="form-group">
<input class="form-control" ng-model="newImage.description" placeholder="Description">
</div>
<div class="form-group">
<input type="file" files-model="newImage.image" required >
</div>
<div class="form-group clearfix">
<button class="btn btn-success pull-right" type="submit" ng-disabled="form.$invalid">Save</button>
</div>
</form>
如您所见,有两个文本input
字段分别绑定到单个对象的属性,我称之为newImage
。该文件也input
被绑定到newImage
对象的属性,但是这次我使用了直接从这里获取的自定义指令。使用此伪指令可以使每次文件内容input
更改时,都将FileList对象放置在binded属性中,而不是a
fakepath
(这是Angular的标准行为)。
我们的控制器代码如下:
angular.module('clientApp')
.controller('MainCtrl', function ($scope, $resource) {
var Image = $resource('http://localhost:3000/images/:id', {id: "@_id"});
Image.get(function(result) {
if (result.status != 'OK')
throw result.status;
$scope.images = result.data;
})
$scope.newImage = {};
$scope.submit = function() {
Image.save($scope.newImage, function(result) {
if (result.status != 'OK')
throw result.status;
$scope.images.push(result.data);
});
}
});
(在这种情况下,我正在本地计算机上的端口3000上运行NodeJS服务器,并且响应是一个包含一个status
字段和一个可选data
字段的json对象)。
为了使文件上传正常工作,我们只需要正确配置$http服务,例如在app对象上的.config调用中即可。具体来说,我们需要将每个发布请求的数据转换为FormData对象,以便以正确的格式将其发送到服务器:
angular.module('clientApp', [
'ngCookies',
'ngResource',
'ngSanitize',
'ngRoute'
])
.config(function ($httpProvider) {
$httpProvider.defaults.transformRequest = function(data) {
if (data === undefined)
return data;
var fd = new FormData();
angular.forEach(data, function(value, key) {
if (value instanceof FileList) {
if (value.length == 1) {
fd.append(key, value[0]);
} else {
angular.forEach(value, function(file, index) {
fd.append(key + '_' + index, file);
});
}
} else {
fd.append(key, value);
}
});
return fd;
}
$httpProvider.defaults.headers.post['Content-Type'] = undefined;
});
该Content-Type
首部设置为undefined
,因为手动设置它来multipart/form-data
将未设定边界值,并且服务器将不能正确解析该请求。
而已。现在你可以使用$resource
到save()
含有标准的数据字段和文件的对象。
警告 这有一些限制:
{ title: "A title", attributes: { fancy: true, colored: false, nsfw: true }, image: null }
那么您需要相应地重构transformRequest函数。 例如,您可以JSON.stringify
嵌套对象,前提是您可以在另一端解析它们
英语不是我的主要语言,所以如果我的解释不清楚,请告诉我,我将尝试重新措辞:)
这只是一个例子。您可以根据您的应用程序需要做什么来扩展它。
我希望这会有所帮助,加油!
正如@david指出的那样,一种侵入性较小的解决方案是仅针对$resource
实际需要此行为的用户定义此行为,而不转换AngularJS提出的每个请求。您可以这样创建自己的代码$resource
:
$resource('http://localhost:3000/images/:id', {id: "@_id"}, {
save: {
method: 'POST',
transformRequest: '<THE TRANSFORMATION METHOD DEFINED ABOVE>',
headers: '<SEE BELOW>'
}
});
至于标题,您应该创建一个满足您要求的标题。您唯一需要指定的是将'Content-Type'
属性设置为undefined
。
这是我的超文本标记语言形式: 我想从本地机器上传图像,并希望读取上传文件的内容。所有这些我都想使用AngularJS来完成。 当我试图打印它是未定义的。
问题内容: 这是我的HTML表单: 我想从本地计算机上传图像,并想读取上传文件的内容。我想使用AngularJS进行的所有操作。 当我尝试打印时,它的值是未定义的。 问题答案: 这里的一些答案建议使用,但不幸的是,这是Internet Explorer 9及更低版本中不可用的浏览器对象。如果需要支持那些较旧的浏览器,则需要使用或使用Flash 的备份策略。 已经有许多Angular.js模块可以执
本文向大家介绍asp.net文件上传解决方案(图片上传、单文件上传、多文件上传、检查文件类型),包括了asp.net文件上传解决方案(图片上传、单文件上传、多文件上传、检查文件类型)的使用技巧和注意事项,需要的朋友参考一下 小编之前也介绍了许多ASP.NET文件上传的解决案例,今天来个asp.net文件上传大集合。 1 使用标准HTML来进行图片上传 前台代码: 后台代码: 2 单文件上传 这是最
本文向大家介绍ASP.NET对大文件上传的解决方案,包括了ASP.NET对大文件上传的解决方案的使用技巧和注意事项,需要的朋友参考一下 首先,我们需要下载这个名为 RanUpLoad 的组件。 下载完成之后,两个 dll 文件添加到项目的引用中区,xml 文件也要复制在项目中的 bin 文件夹下,也就是最后三个文件都要存在于 bin 文件夹中。 接着,上传控件还是用 ASP.NET 中自带的 Fi
本文向大家介绍asp.net批量多选文件上传解决方案,包括了asp.net批量多选文件上传解决方案的使用技巧和注意事项,需要的朋友参考一下 多选文件上传,已经非常多了,选择性多了可能有时候要比较下哪个更合适,结合到项目中使用更方便才是最重要的。很多的多选上传基本上都是调用的swf文件,确实用flash 或flex开发一个多选上传的功能很方便,比如flex里内置的FileReferenceList对
问题内容: 我需要使用Laravel 5.1作为后端将图像和视频文件上传到Angular应用程序中的服务器。所有Ajax请求都需要首先发送到Laravel控制器,并且我们在这里有代码说明文件到达那里后如何处理。以前,我们已经完成了普通的HTML表单以将文件上传提交到控制器,但是在这种情况下,我们需要避免刷新表单的页面,因此我尝试通过Angular在Ajax中进行尝试。 我需要将以前通过HTML表单