【问题标题】:React ajax request with multipart file and json data使用多部分文件和 json 数据响应 ajax 请求
【发布时间】:2020-04-01 18:23:32
【问题描述】:

我有一个这样的基本请求:

export const request = (options) => {
    const headers = new Headers({
        'Content-Type': 'application/json',
    });

    if (Common.getToken()) {
        headers.append('Authorization', 'Bearer ' + Common.getToken())
    }

    const defaults = {headers: headers};
    options = Object.assign({}, defaults, options);

    return fetch(options.url, options)
        .then(response =>
            response.json().then(json => {
                if (!response.ok) {
                    return Promise.reject(json);
                }
                return json;
            })
        );
};

还有我的 ajax 请求:

onCreateNewPost(postDataRequest, photoBody) {
    const formData = new FormData();
    formData.append('photo', photoBody);
    formData.append('postData', JSON.stringify(postDataRequest));

    return request({
        url: API_BASE_URL + '/posts/new-post',
        method: 'POST',
        body: formData
    });
};

其中 postDataRequest - json 对象包括帖子标题、描述等... photoBody - 图像文件。 在后端我有一个控制器的方法:

@PostMapping(value = "/api/posts/new-post")
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity createNewPost(@CurrentUser UserPrincipal currentUser,
                                    @RequestBody NewPostDataRequest postRequest,
                                    @RequestParam MultipartFile photo) {

    // method body


    return ResponseEntity.ok(new ActionCompleteResponse(true));
}

但是当我发送请求时,我得到状态码:400。这是什么问题?我可以单独发送 json 数据或多部分数据,但我不知道如何将它们与一个请求一起传输。我试图在请求中放置没有 Content-Type 的标头,如下面的代码所示,以便请求本身指示它,但作为响应,我得到代码 415。

onCreateNewPost(postDataRequest, photoBody) {
    const formData = new FormData();
    formData.append('photo', photoBody);
    formData.append('postData', JSON.stringify(postDataRequest));
    const headers = new Headers({});

    if (Common.getToken()) {
        headers.append('Authorization', 'Bearer ' + Common.getToken());
    }

    return request({
        url: API_BASE_URL + '/posts/new-post',
        headers: headers,
        method: 'POST',
        body: formData
    });
};

我该怎么办?

【问题讨论】:

    标签: javascript ajax reactjs spring


    【解决方案1】:

    好的,我找到了解决方案: 1.清除headers数据(授权令牌除外) 2. 添加@PostMapping consumes = MediaType.MULTIPART_FORM_DATA_VALUE 并添加@RequestPart 到方法参数

    ajax 请求如:

      onCreateNewPost(postDataRequest, photoBody) {
            const formData = new FormData();
            formData.append('post', new Blob([JSON.stringify(postDataRequest)], {
                type: "application/json"
            }));
            formData.append('photo', photoBody);
            const headers = new Headers({});
    
            if (Common.getToken()) {
                headers.append('Authorization', 'Bearer ' + Common.getToken())
            }
    
            return request({
                url: API_BASE_URL + '/posts/new-post',
                method: 'POST',
                headers: headers,
                body: formData
            });
        };
    

    和弹簧控制器一样

    @PostMapping(value = "/new-post", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity createNewPost(@CurrentUser UserPrincipal currentUser,
                                        @RequestPart("post") @Valid PostEntity post,
                                        @RequestPart("photo") @Valid MultipartFile photo) throws IOException {
        post.setAuthor(currentUser.getUsername());
        post.setAuthorId(currentUser.getId());
        post.setCommentsCount(0L);
        post.setDate(LocalDate.now());
        post.setPhoto(photo.getBytes());
    
        postService.save(post);
    
        return ResponseEntity.ok(new ActionCompleteResponse(true));
    }
    

    【讨论】:

      【解决方案2】:

      @Sergey Scream 解决方案是正确的,我只是想添加一些信息来澄清问题。

      因此,如果您想使用 FormData 发送 json 和文件,则必须将 json 包装在一个 blob 中,包括他所做的类型:

      formData.append('post', new Blob([JSON.stringify(postDataRequest)], {
                  type: "application/json"
              }));
      

      像这样添加你的 json 是行不通的:

      formData.append('post', JSON.stringify(postDataRequest));
      

      【讨论】:

      • 非常感谢,这个答案可以节省我的时间。
      【解决方案3】:

      您将 request 中的 Content-Type 设置为 application/json,但将 body 设置为 onCreateNewPost 中的数据。如果您从 request 中删除了第 3 行,那么您当前的解决方案应该可以工作。

      您还要在onCreateNewPostrequest 中设置两次授权标头。

      【讨论】:

      • 在最后一个代码片段中,我演示了我的请求,但没有设置 Content-Type,所以它不起作用,我得到代码 415
      猜你喜欢
      • 1970-01-01
      • 2021-10-08
      • 1970-01-01
      • 1970-01-01
      • 2011-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多