我在客户端的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_问题是相同的,因为它无法找到所需的资源
对这个问题的任何想法?
答案 0 :(得分:2)
查看您的错误消息,我看到:
否&#39;访问控制 - 允许 - 来源&#39;标题存在
您确定要添加正确的标题吗?
我们使用过滤器来确保所有请求都正确添加了这些标头:
这是我们使用的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)
在Chrome中尝试此扩展程序,它可以帮助您解决问题
答案 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 =“/ **”