S
S
Stepan2021-10-02 18:48:01
JavaScript
Stepan, 2021-10-02 18:48:01

How to submit a form containing text fields and a file in JSON format using JavaScript?

There is a form with two text fields - "Title" and "Description" - and a file attachment field.
I need to send this form as a POST request, after converting it to JSON.
Question: how?
Most of the examples that I found describe either how to send a separate text, or a separate file.

Requests are processed by RestController Spring:

@PostMapping("/my/bookunits")
    public ResponseEntity<ApiResponse> createBookUnit(@CurrentUser UserPrincipal currentUser,
                                                      @Valid @ModelAttribute BookUnitRequest bookUnitRequest) {
        User user = userService.loadUserById(currentUser.getId());
        bookUnitService.createBookUnit(user, bookUnitRequest);
        return new ResponseEntity<>(new ApiResponse(Boolean.TRUE, "processing"), HttpStatus.ACCEPTED);
    }


@Data
public class BookUnitRequest {
    @NotBlank
    private String title;

    @NotBlank
    private String description;

    private MultipartFile bookFile;
}


I understand that all content of the form Content-type must be multipart / form-data, right?
In Poster, I tried it through the form-data data type in Body, everything was accepted.
Is it possible in JSON? If not, tell me how to fix the request:
$("#newBookUnitForm").submit(function (e) {
    let authToken = localStorage.getItem("accessToken");
    let url = "http://localhost:8080/api/my/bookunits";
    console.log("Попытка загрузить новую книгу на: " + url);

    let newBookUnitRequest = {
        "title": document.getElementById("newBookUnitTitle").value,
        "description": document.getElementById("newBookUnitDescription").value,
        "bookfile": document.getElementById("newBookUnitFile").value
    }
    let newBookUnitRequestJson = JSON.stringify(newBookUnitRequest);

    let xhr = new XMLHttpRequest();
    xhr.open('POST', url, true)
    xhr.setRequestHeader("Content-type", "application/json; charset=utf-8");
    xhr.setRequestHeader("Authorization", authToken);
    xhr.onload = function () {
        if (xhr.readyState === 4) {
            switch (xhr.status) {
                case 202:
                    let resp = JSON.parse(xhr.responseText);
                    console.log("Файл принят. Ответ сервера: " + resp.message);
                    break;
                case 401:
                    console.log("Код ответа 401. Ошибка авторизации.");
                    break;
                default:
                    console.log("Код ответа: " + xhr.status + ", ответ сервера: " + xhr.responseText);
            }
        }
    }
    xhr.send(newBookUnitRequestJson);
    e.preventDefault();
})

Answer the question

In order to leave comments, you need to log in

2 answer(s)
O
Orkhan Hasanli, 2021-10-02
@steff

I understand that all content of the form Content-type must be multipart / form-data, right?

Yes that's right.
Also, don't forget to send the csrf token if you have it enabled in your security settings. Some template engines (for example, thymeleaf) do this automatically, but when submitting the form content using js, you must also send csrf. To do this, a meta tag is added to the head, into which the csrf token is inserted.
Then, using js, you need to get the value of this tag (token) and send it with the form.
Details here:
https://www.baeldung.com/spring-security-csrf
Section 3.4 Using Json - https://www.baeldung.com/spring-security-csrf#4-us...
e.preventDefault();
Most likely this line should be above all. How would you stop the form submission first and then do the rest. Otherwise, your form will be submitted, and then the rest of the code will be executed.
And here is the answer to your question:
https://stackoverflow.com/questions/49845355/sprin...
Both the first answer and the second describe the option of submitting a form using js with a file and other data.

N
Nadim Zakirov, 2021-10-03
@zkrvndm

You can convert your files to base64 text and send this text to the server, inside JSON along with the rest of the data. In short, I see no problem.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question