我想在JSFiddle的这个angularjs html5上传示例中删除文件:
http://jsfiddle.net/danielzen/utp7j/
由grails控制器上传到后端。 在尝试完成此操作时,我创建了一个简单的grails控制器:
class UploadController {
def index() {
if (request instanceof MultipartHttpServletRequest){
for(filename in request.getFileNames()){
MultipartFile file = request.getFile(filename)
String newFileName = UUID.randomUUID().toString() + file.originalFilename.substring(file.originalFilename.lastIndexOf("."))
file.transferTo(new File("/home/myuser/temp/$newFileName"))
}
}
render "ok"
}
}
然后我打开一个ajax XmlHttpRequest2 POST给grails控制器:
xhr.open("POST", "http://localhost:8080/app/upload")
但是grails控制器无法将请求强制转换为MultipartHttpServletRequest, 可能是因为这种调用grails控制器的ajax方式不使用multipart / form-data上传方式。 我尝试在xhr上为enctype multipart / form-data设置标题无效。
我现在完全陷入困境,想知道如何处理grails控制器中上传的文件
答案 0 :(得分:1)
我使用内置的Chrome开发者工具跟踪由XmlHttpRequest.send(formData)调用生成的POST请求。 令我惊讶的是,请求方法不是类型为POST的类型为enctype = multipart / form-data但类型为OPTIONS。
这个提示让我走上正轨,在Google的帮助下,我发现这个OPTIONS请求是按照CORS定义的规范进行的预检检查。
来自wikipdia:
跨域资源共享(CORS)是一种允许的机制 网页上的JavaScript将XMLHttpRequests发送到另一个域, 不是JavaScript源自的域。[1]这样的“跨域” 否则,Web浏览器将禁止请求 原产地安全政策。 CORS定义了浏览器和浏览器的方式 服务器可以交互以确定是否允许 跨性别请求。[2]它比仅允许更强大 同源请求,但它比简单地允许所有请求更安全 这种跨域请求。
CORS标准通过添加允许服务器的新HTTP标头来工作 为允许的原始域提供资源。浏览器支持这些 标题并强制执行它们建立的限制。另外,为 可能对用户数据造成副作用的HTTP请求方法(in 特别是,对于GET以外的HTTP方法,或者对于POST使用 某些MIME类型),规范要求浏览器 “预检”请求,从服务器请求支持的方法 使用HTTP OPTIONS请求标头,然后,在“批准”时 服务器,使用实际的HTTP请求发送实际请求 方法。服务器还可以通知客户端是否“凭据” (包括Cookie和HTTP身份验证数据)应与之一起发送 请求。
因为我的grails(tomcat)服务器是从localhost:8080运行而我的html / javascript是在localhost:63342上的内置http服务器上的WebStorm IDE中运行的,所以XmlHttpRequest实际上是CORS,因为不同的端口号在同一主机上也被视为交叉起源。
因此,我需要确保Grails(tomcat)服务器允许这样做,并且我能够使用Grails的优秀cors插件执行此操作,该插件可以在https://github.com/davidtinker/grails-cors找到
之后,该请求被识别为MultipartHttpServletRequest
,该文件可以从params
答案 1 :(得分:0)
从小提琴上传时,可以看一眼网络:
------WebKitFormBoundarygZi30fqQLB2A9qAC
Content-Disposition: form-data; name="uploadedFile"; filename="file.txt"
Content-Type: text/javascript
------WebKitFormBoundarygZi30fqQLB2A9qAC--
我相信你会得到一个“uploadedFile”作为Grails的param键,所以你可以编写一个控制器动作,如:
def uploadFile(CommonsMultipartFile uploadedFile) {
///accessing the file data: uploadedFile.bytes, uploadedFile.contentType, uploadedFile.originalFilename
}
为了确保传递的内容,请在动作接收的params地图上进行调试,并相应地更改动作方法参数名称。
答案 2 :(得分:0)
<body ng-controller="FileUploadCtrl">
$scope.selectedFile=[];
$scope.onFileSelect = function ($files) {
$scope.uploadProgress = 0;
$scope.selectedFile = $files;
};
$scope.myData = {};
$scope.upload = function(){
var formData = new FormData();
formData.append("file", $scope.selectedFile[0]);
formData.append("data", myData.message.value);
$http.post('api/upload', formData, {
transformRequest: angular.identity,
headers: {
'enctype': 'multipart/form-data',
'Content-Type': undefined
}
})
.success(function(){
alert("done");
})
.error(function(){
alert("failed");
});
</body>
<form ng-submit="upload()" method="post" enctype="multipart/form-data" name="myData"> <div>
<textarea rows="3" name="message" placeholder="Send Message"></textarea>
<input type="file" ng-file-select="onFileSelect($files)" />
</div>
<button type="submit" class="btn btn-primary">upload</button>
</form>