0

我想要在 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 控制器中处理上传的文件

4

3 回答 3

1

我使用内置的 Chrome 开发者工具跟踪了由 XmlHttpRequest.send(formData) 调用生成的 POST 请求。令我惊讶的是,请求方法不是带有 enctype=multipart/form-data 的 POST 类型,而是 OPTIONS 类型。

这个提示让我走上了正确的轨道,在谷歌的帮助下,我发现这个 OPTIONS 请求是作为 CORS 定义的每个规范的预检检查发生的。

来自维基百科:

跨域资源共享 (CORS) 是一种机制,它允许网页上的 JavaScript 向另一个域发出 XMLHttpRequest,而不是 JavaScript 源自的域。 [1] 否则,根据同源安全策略,Web 浏览器将禁止此类“跨域”请求。CORS 定义了浏览器和服务器可以交互以确定是否允许跨域请求的方式。 [2] 它比只允许同源请求更强大,但它比简单地允许所有此类跨源请求更安全。

CORS 标准通过添加新的 HTTP 标头来工作,这些标头允许服务器向允许的源域提供资源。浏览器支持这些标头并强制执行它们建立的限制。此外,对于可能对用户数据造成副作用的 HTTP 请求方法(特别是对于 GET 以外的 HTTP 方法,或者对于某些 MIME 类型的 POST 使用),规范要求浏览器“预检”请求,请求支持的方法使用 HTTP OPTIONS 请求标头从服务器发送,然后,在服务器“批准”后,使用实际的 HTTP 请求方法发送实际请求。服务器还可以通知客户端是否应随请求发送“凭据”(包括 Cookie 和 HTTP 身份验证数据)。

因为我的 grails (tomcat) 服务器是从 localhost:8080 运行的,而我的 html/javascript 是从 WebStorm IDE 内的 localhost:63342 的内置 http 服务器上运行的,所以 XmlHttpRequest 是有效的 CORS,因为不同的端口号在同一个主机也被认为是跨域的。

因此,我需要确保 Grails (tomcat) 服务器允许这样做,并且我能够使用 Grails 的优秀 cors 插件来做到这一点,该插件可以在https://github.com/davidtinker/grails-cors找到

之后,请求被识别为 aMultipartHttpServletRequest并且可以从中获取文件params

于 2013-10-16T16:57:52.390 回答
0

从小提琴上传时查看网络,您会得到:

------WebKitFormBoundarygZi30fqQLB2A9qAC
Content-Disposition: form-data; name="uploadedFile"; filename="file.txt"
Content-Type: text/javascript


------WebKitFormBoundarygZi30fqQLB2A9qAC--

我相信你会得到一个“uploadedFile”作为 Grails 的参数键,所以你可以编写一个控制器动作,如:

def uploadFile(CommonsMultipartFile uploadedFile) {
    ///accessing the file data: uploadedFile.bytes, uploadedFile.contentType, uploadedFile.originalFilename
}

为了确定传递的是什么,请在操作接收的参数映射上进行调试,并相应地更改操作方法参数名称。

于 2013-10-16T01:39:42.223 回答
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>
于 2014-10-24T11:23:04.973 回答