在spring mvc

时间:2016-08-28 10:41:35

标签: java angularjs spring-mvc cors ng-file-upload

我在客户端的Angular中使用ng-file-upload将文件(图像,文本等)发送到Spring Boot Application。

我的客户端在Xampp中使用url" localhost"同时让spring实例与url" localhost:8080"单独运行。双方的已启用,其他所有请求都被成功接受。

客户端代码:

        Upload.upload({
        url: 'http://localhost:8080/file/upload',
        method:'POST',
            data: {
            uploadedPicture: file,
            uploadedFrom: 'recipe'
        },
    }).then(function(response) {
        $timeout(function() {
            $scope.result = response.data;
        });
    }, function(response) {
        if (response.status > 0) $scope.errorMsg = response.status + ': ' + response.data;
    }, function(evt) {
        $scope.progress = parseInt(100.0 * evt.loaded / evt.total);
    });

服务器端代码:

@CrossOrigin
@RequestMapping(method = RequestMethod.POST, value = "/file/upload")
public String handleFileUpload(@RequestParam("file") MultipartFile file,
                               RedirectAttributes redirectAttributes) {
    if (!file.isEmpty()) {
        try {
            Files.copy(file.getInputStream(), Paths.get(ROOT, file.getOriginalFilename()));
            redirectAttributes.addFlashAttribute("message",
                    "You successfully uploaded " + file.getOriginalFilename() + "!");
        } catch (IOException|RuntimeException e) {
            redirectAttributes.addFlashAttribute("message", "Failued to upload " + file.getOriginalFilename() + " => " + e.getMessage());
        }
    } else {
        redirectAttributes.addFlashAttribute("message", "Failed to upload " + file.getOriginalFilename() + " because it was empty");
    }

    return "redirect:/";
} 

我通过使用get方法将相同代码的get请求发送到同一资源来尝试使用cors。但是当我发送带有多部分表单数据(图像或任何其他文件)的post请求时,它拒绝OPTIONS请求。< / p>

   OPTIONS http://localhost:8080/file/upload
   XMLHttpRequest cannot load http://localhost:8080/file/upload. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. The response had HTTP status code 403.

我已经通过邮递员测试了这个资源,它上传的文件没有错误。

编辑: 我已尝试将http更改为https,并且它提供错误,因为OPTIONS https://localhost:8080/file/upload net :: ERR_TIMED_OUT_问题是相同的,因为它无法找到所需的资源

对这个问题的任何想法?

7 个答案:

答案 0 :(得分:2)

查看您的错误消息,我看到:

  

否&#39;访问控制 - 允许 - 来源&#39;标题存在

您确定要添加正确的标题吗?

我们使用过滤器来确保所有请求都正确添加了这些标头:

  • Access-Control-Allow-Origin:*
  • Access-Control-Allow-Methods:POST,GET,OPTIONS,DELETE
  • Access-Control-Max-Age:3600
  • Access-Control-Allow-Headers:x-requested-with

这是我们使用的Filter类:

SimpleCORSFilter.java

 @Component
 public class SimpleCORSFilter implements Filter {

        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
            HttpServletResponse response = (HttpServletResponse) res;
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
            chain.doFilter(req, res);
        }

        public void init(FilterConfig filterConfig) {}

        public void destroy() {}

    }

答案 1 :(得分:1)

只需将@CrossOrigin注释更改为:

@CrossOrigin(origins = "*", methods = {RequestMethod.POST, RequestMethod.OPTIONS}, allowedHeaders = {"Content-Type", "X-Requested-With", "accept", "Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers"}, exposedHeaders = {"Access-Control-Allow-Origin", "Access-Control-Allow-Credentials"})

答案 2 :(得分:0)

答案 3 :(得分:0)

首先检查您的安全设置,因为您显然获得403作为状态代码。也许你的重定向最终导致问题,试试没有它。

这是一个代码示例,我刚才用来添加CORS-headers:

@RequestMapping(value="/GetSomething", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public ResponseEntity<String> getSomething() throws IOException {
    HttpHeaders responseHeaders = new HttpHeaders();
    //need for cross-domain requests
    responseHeaders.add("Access-Control-Allow-Origin", "*");
    //this one is needed, if your browser should send cookies
    responseHeaders.add("Access-Control-Allow-Credentials", "true");
    ...
    responseHeaders.setContentLength(resp.getBytes("UTF-8").length);
    return new ResponseEntity<String>(resp, responseHeaders, HttpStatus.OK);
}

编辑:删除了会话参数

EDIT2:你能检查一下你的POST请求中的代码是否真的被执行了吗?在函数中创建一些日志。如果您的代码未执行,那么您显然存在安全设置问题,并且您的请求不会通过安全层。 CORS是基于客户端的功能,它只能在浏览器从服务器获取数据后阻止数据!

答案 4 :(得分:0)

我之前在我目前的项目中遇到过这个问题,经过大量RND和一些实验后,我发现问题出在内容类型上,每当有图片上传时都会占用上传内容类型的问题在这里很多。

我没有对此进行测试,但在尝试此操作后请通过替换您的代码...

告诉我
            var fd = new FormData();
            fd.append('uploadedPicture', file);
            fd.append('uploadedFrom', 'recipe');

            Upload.upload({
                url: 'http://localhost:8080/file/upload',
                method: 'POST',
                data: fd,
                transformRequest: angular.identity,
                headers: {'Content-Type': undefined},
            }).then(function (response) {
                $timeout(function () {
                    $scope.result = response.data;
                });
            }, function (response) {
                if (response.status > 0)
                    $scope.errorMsg = response.status + ': ' + response.data;
            }, function (evt) {
                $scope.progress = parseInt(100.0 * evt.loaded / evt.total);
            });

请在尝试之后告诉我。

答案 5 :(得分:0)

从Ajax调用返回重定向是没有意义的。首先确定问题是与表单发布有关还是与后续操作有关。为此,请按以下方式更改您的控制器:

@CrossOrigin
@RequestMapping(method = RequestMethod.POST, value = "/file/upload")
@ResponseBody
public String handleFileUpload(@RequestParam("file") MultipartFile file) {

    String status = null;

    if (!file.isEmpty()) {
        try {
            Files.copy(file.getInputStream(), Paths.get(ROOT, file.getOriginalFilename()));
            status = "okay";

        } catch (IOException|RuntimeException e) {
            status = "error";  
        }
    } else {
        status = "error";
    }

    return "status"; // a literal string
}

我还要注意,从前端发送的参数与后端预期的不匹配。您在前端的哪个位置指定了名为&#39; file&#39;的参数。控制器将映射到指定的RequestParam?

这个库有一个使用Spring MVC的端到端示例:

https://github.com/danialfarid/ng-file-upload/wiki/spring-mvc-example

注意参数名称如何在两侧匹配。

答案 6 :(得分:0)

添加内容类型,请参阅此答案,它可能会有所帮助Request not found ajax spring mvc和originins =“/ **”