javaajaxangularrestgrizzly

HTTP POST Angular to Java. Cannot send multiple parameters with different types


I am trying to send an uploaded file (FormData from Angular) and a string in the same HTTP POST request to backend (Java using Grizzly server and Ajax for REST services). The problem is that I receive HTTP 400 Bad Request because the file is not correctly mapped:

jersey message: Can not construct instance of java.io.InputStream: abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type

In Frontend I have a class named Form created using ng g class Form, which contains:

export class Form {
    private file:FormData;
    private bookName: String;

    constructor(file:FormData, bookName: String) {
        this.file = file;
        this.bookName = bookName;
    }
}

The HTTP POST method from Frontend is:

  sendFormData() {
    const form  = new Form(this.testData, this.bookName);

    this.pdfService.sendFormData(form).subscribe((res) => {
      console.log(res);
    });
  }

Above this.testData has the type FormData and this.bookName is a string. They both contain the expected input values.

The pdfService.sendFormData is:

  public sendFormData(form: Form) {
    console.log("sending to " + this.baseUrl + "uploadFile")
    return this.http.post(this.baseUrl + "uploadFile", form, { responseType: 'text' });
  }

In Backend I have a class Form.java (the mapped class):

public class Form {
    String bookName;
    InputStream file;
    ... (getters & setters & constructor)
}

and the HTTP POST method is:

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.TEXT_HTML)
    @Path("uploadFile")
    public Response convertPdfToHtml(Form form) {
            ...
    }

To get the mapped string I use: form.getBookName() and to get the mapped file I use: form.getFile().

As I said, the problem is that the file from Frontend is not correctly mapped on the InputStream from Backend.

What type should I use to map a FormData from Frontend to a type in Backend? Or what other implementations could I use to send a file and a string in the same POST request?

Thanks.


Solution

  • in POST method you should provide object of type FormData, and there

    export class Form {
      private file: File;
      private bookName: String;
    
      constructor(file:File, bookName: String) {
        this.file = file;
        this.bookName = bookName;
      }
    }
    
    
    public sendFormData(form: Form) {
      const formData = new FormData();
      formData.append('bookName', form.bookName);
      formData.append('file', form.file, form.file.name);
    
      console.log("sending to " + this.baseUrl + "uploadFile")
      return this.http.post(this.baseUrl + "uploadFile", formData, {responseType: 'text'});
    }
    

    and you'll get post with content-type multipart/form-data