CORS文件通过Axios上传到Spring启动服务器

时间:2018-05-29 14:31:21

标签: spring-boot vue.js cors axios multipartform-data

我一直在尝试使用Axios将文件(图像或东西)上传到Spring启动REST服务器,但它根本无法正常工作。除文件外,其他有效负载均为find。例如,我发送字符串,整数和图像,但服务器只接收字符串和整数。奇怪的是,当我尝试使用Postman进行操作时,一切都很顺利,包括文件。

@PostMapping
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_MASTER')")
public ResponseEntity<ApiResponse> uploadProduct(@ModelAttribute ProductRequest productRequest) {
    System.out.println("-----------------");
    System.out.println("name: " + productRequest.getName());
    System.out.println("price: " + productRequest.getPrice());
    System.out.println("is empty: " + productRequest.getImage().isEmpty());
    productRequest.getImage().forEach(o-> System.out.println(o.getOriginalFilename()));
    System.out.println("-----------------");
    return null;
}

这是我的测试控制器。 .getImage()始终返回true。

onSubmit() {
    const data = new FormData();
    data.append('name', this.name);
    data.append('price', this.price);
    data.append('files', this.image);
    const token = localStorage.getItem('token');
    const auth = {
       headers: { Authorization: 'Bearer '.concat(token) },
    };
    axios.post('http://192.168.0.2:8080/api/products/', data, auth).then((response) => {
            if (response.status === 200) {
              alert('okay');
            } else if (response.status === 401) {
              alert('not okay');
            }
          }).catch((error) => {
            console.log(error);
          });
}

这是上面的javascript代码。

另外,我在服务器上设置过滤器,允许CORS如下所示。

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
    HttpServletResponse response = (HttpServletResponse) res;
    HttpServletRequest request = (HttpServletRequest) req;

    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Allow-Headers", "*");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Credentials", "true");

    if (!(request.getMethod().equalsIgnoreCase("OPTIONS"))) {
        try {
            chain.doFilter(req, res);
        } catch(Exception e) {
            e.printStackTrace();
        }
    } else {
        System.out.println("Pre-flight");
        response.setHeader("Access-Control-Allow-Methods", "POST,GET,DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "authorization, content-type," +
                "access-control-request-headers,access-control-request-method,accept,origin,authorization,x-requested-with");
        response.setStatus(HttpServletResponse.SC_OK);
    }

}

Vue.js dev服务器端口:8081,Spring:8080,我附上了请求标头和有效负载的屏幕截图。

req headers

req payloads

感谢您的阅读。

    General
    Request URL: http://192.168.0.2:8080/api/products/
    Request Method: POST
    Status Code: 200 
    Remote Address: 192.168.0.2:8080
    Referrer Policy: no-referrer-when-downgrade

    Response Headers
    Access-Control-Allow-Credentials: true
    Access-Control-Allow-Headers: *
    Access-Control-Allow-Methods: POST, PUT, GET, OPTIONS, DELETE
    Access-Control-Allow-Origin: *
    Access-Control-Max-Age: 3600
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Content-Type: application/json;charset=UTF-8
    Date: Tue, 29 May 2018 15:12:43 GMT
    Expires: 0
    Pragma: no-cache
    Transfer-Encoding: chunked
    X-Content-Type-Options: nosniff
    X-Frame-Options: DENY
    X-XSS-Protection: 1; mode=block

    Request Headers
    Provisional headers are shown
    Accept: application/json, text/plain, */*
    Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxMiIsImlhdCI6MTUyNzYwNTg1MywiZXhwIjoxNTI3NjkyMjUzfQ.GJSdT0YgpKVhai9MQN6tPRDNgmmnCPchwNiLY_XUGlwQE-aMZcUpANEIvaz6bRlLSkHYnceJ63rx1fJIdxyE_Q
    Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryW5gjajdcI3pBL6q7
    Origin: http://localhost:8081
    Referer: http://localhost:8081/menu
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36

    Request Payload
    ------WebKitFormBoundaryW5gjajdcI3pBL6q7
    Content-Disposition: form-data; name="name"

    114d
    ------WebKitFormBoundaryW5gjajdcI3pBL6q7
    Content-Disposition: form-data; name="price"

    1234
    ------WebKitFormBoundaryW5gjajdcI3pBL6q7
    Content-Disposition: form-data; name="files"

    data:image/png;base64,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 more

并且控制台说:

log.js?4244:23 [HMR] Waiting for update signal from WDS...
Menu.vue?64be:224 eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxMiIsImlhdCI6MTUyNzYwNTg1MywiZXhwIjoxNTI3NjkyMjUzfQ.GJSdT0YgpKVhai9MQN6tPRDNgmmnCPchwNiLY_XUGlwQE-aMZcUpANEIvaz6bRlLSkHYnceJ63rx1fJIdxyE_Q
Menu.vue?64be:228 {headers: {…}}
Menu.vue?64be:233 [__ob__: Observer]
Menu.vue?64be:230 {data: Array(22), status: 200, statusText: "", headers: {…}, config: {…}, …}
vue.esm.js?efeb:591 [Vue warn]: Invalid prop: type check failed for prop "src". Expected String, got File.
warn @ vue.esm.js?efeb:591
assertProp @ vue.esm.js?efeb:1632
validateProp @ vue.esm.js?efeb:1560
createFunctionalComponent @ vue.esm.js?efeb:4045
createComponent @ vue.esm.js?efeb:4250
_createElement @ vue.esm.js?efeb:4420
createElement @ vue.esm.js?efeb:4357
vm._c @ vue.esm.js?efeb:4489
render @ Menu.vue?0af2:380
Vue._render @ vue.esm.js?efeb:4544
updateComponent @ vue.esm.js?efeb:2788
get @ vue.esm.js?efeb:3142
run @ vue.esm.js?efeb:3219
flushSchedulerQueue @ vue.esm.js?efeb:2981
(anonymous) @ vue.esm.js?efeb:1837
flushCallbacks @ vue.esm.js?efeb:1758
vue.esm.js?efeb:591 [Vue warn]: Invalid prop: type check failed for prop "src". Expected String, got File.
warn @ vue.esm.js?efeb:591
assertProp @ vue.esm.js?efeb:1632
validateProp @ vue.esm.js?efeb:1560
createFunctionalComponent @ vue.esm.js?efeb:4045
createComponent @ vue.esm.js?efeb:4250
_createElement @ vue.esm.js?efeb:4420
createElement @ vue.esm.js?efeb:4357
vm._c @ vue.esm.js?efeb:4489
render @ Menu.vue?0af2:659
Vue._render @ vue.esm.js?efeb:4544
updateComponent @ vue.esm.js?efeb:2788
get @ vue.esm.js?efeb:3142
run @ vue.esm.js?efeb:3219
flushSchedulerQueue @ vue.esm.js?efeb:2981
(anonymous) @ vue.esm.js?efeb:1837
flushCallbacks @ vue.esm.js?efeb:1758
vue.esm.js?efeb:591 [Vue warn]: Invalid prop: type check failed for prop "src". Expected String, got File.
warn @ vue.esm.js?efeb:591
assertProp @ vue.esm.js?efeb:1632
validateProp @ vue.esm.js?efeb:1560
createFunctionalComponent @ vue.esm.js?efeb:4045
createComponent @ vue.esm.js?efeb:4250
_createElement @ vue.esm.js?efeb:4420
createElement @ vue.esm.js?efeb:4357
vm._c @ vue.esm.js?efeb:4489
render @ Menu.vue?0af2:839
Vue._render @ vue.esm.js?efeb:4544
updateComponent @ vue.esm.js?efeb:2788
get @ vue.esm.js?efeb:3142
run @ vue.esm.js?efeb:3219
flushSchedulerQueue @ vue.esm.js?efeb:2981
(anonymous) @ vue.esm.js?efeb:1837
flushCallbacks @ vue.esm.js?efeb:1758
Menu.vue?64be:348 114d
Menu.vue?64be:354 eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxMiIsImlhdCI6MTUyNzYwNTg1MywiZXhwIjoxNTI3NjkyMjUzfQ.GJSdT0YgpKVhai9MQN6tPRDNgmmnCPchwNiLY_XUGlwQE-aMZcUpANEIvaz6bRlLSkHYnceJ63rx1fJIdxyE_Q
Menu.vue?64be:359 {headers: {…}}headers: Authorization: "Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxMiIsImlhdCI6MTUyNzYwNTg1MywiZXhwIjoxNTI3NjkyMjUzfQ.GJSdT0YgpKVhai9MQN6tPRDNgmmnCPchwNiLY_XUGlwQE-aMZcUpANEIvaz6bRlLSkHYnceJ63rx1fJIdxyE_Q"__proto__: constructor: ƒ Object()hasOwnProperty: ƒ hasOwnProperty()isPrototypeOf: ƒ isPrototypeOf()propertyIsEnumerable: ƒ propertyIsEnumerable()toLocaleString: ƒ toLocaleString()toString: ƒ toString()valueOf: ƒ valueOf()__defineGetter__: ƒ __defineGetter__()__defineSetter__: ƒ __defineSetter__()__lookupGetter__: ƒ __lookupGetter__()__lookupSetter__: ƒ __lookupSetter__()get __proto__: ƒ __proto__()set __proto__: ƒ __proto__()__proto__: Object

0 个答案:

没有答案