Uploading files from Angular to Spring Boot encounters an issue with multipart boundary rejection

I am facing a challenge in uploading form data from Angular to Spring Boot server.

Basically, in Spring Boot, I define the following classes:

data class Photo(
    val id: Long = 0L,
    val file: MultipartFile
)

data class PostRequest(
    @field:Size(min = 1, max = 100)
    val title: String,

    val photos: List<Photo> = mutableListOf()
)

This is handled via Controller:

fun createPost(@Valid @ModelAttribute postRequest: PostRequest)

In Angular, I have created a form as follows:

this.postForm = this.fb.group({
   title: ["", [Validators.required, Validators.minLength(1)]],
   photos: this.fb.array([]),
});

When a user uploads a photo, the following lines are executed:

const photosArray = this.postForm.get("photos") as FormArray;
          
const newPhotoGroup = this.fb.group({
  id: "",
  file: event.target.result,
});
          
photosArray.push(newPhotoGroup);

Lastly, a FormData object is constructed:

const formData = new FormData();
formData.append("title", this.postForm.get("title")?.value);
formData.append("photos", this.postForm.get("photos")?.value);

To send this form data to the API, the following function is utilized:

 postRequest<T>(url: string, body: any): Observable<HttpResponse<T>> {
    const headers = new HttpHeaders({
      "Content-Type": "multipart/form-data",
    });

    return this.http.post<T>(url, body, {
      headers,
      observe: "response",
      withCredentials: true,
    });
  }

Upon inspecting developer tools, the request appears like this:

https://i.sstatic.net/blz6t.png

However, Spring Boot raises an issue:

org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found

If anyone can provide insight on this matter, it would be greatly appreciated. Thank you.

Answer №1

photos form control contains an array of objects that are sent in the request as [object Object], leading to an error.

To resolve this, you must iterate through the array and append each file individually:

const formData = new FormData();
formData.append("title", this.postForm.get("title")?.value);
// loop files and append them
this.postForm.get("photos")?.value.forEach((obj:any, i:number)=>{
    formData.append("photos", obj.file); // ensure obj.file is of type File
});

When adding a file to the array, verify that it is of type File (if event.target.result is currently a string, consider using event.target.file or adding a new property like 'uploadFile' for later use in formData):

const newPhotoGroup = this.fb.group({
    id: "",
    file: event.target.result, // should be File from event.target.file
  });

If including custom file data like an ID with the file, it cannot be in the same formData key as the file itself

You can either use the ID instead of the filename:

formData.append("photos", obj.file, obj.id)

Or adjust the upload process similar to this example: sending JSON object along with file using FormData in ajax call and accessing the json object in PHP


Lastly, send the request without specifying content-type headers, as FormData will handle it automatically:

return this.http.post<T>(url, body, {
    observe: "response",
    withCredentials: true,
  });

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing a Chrome profile is ineffective in WebdriverIO

Instead of dealing with signing in every time, I prefer pre-signing in on my profile. Even though I am using the code below, it's still not loading in the specified profile. What can I do to resolve this issue? const browser = await remote({ capabi ...

Tips for setting up a mdl-dialog using a declarative approach

I want to incorporate a mdl-dialog into my component following the example provided here: However, when I try to do so, the compiler throws an error stating: Can't bind to 'mdl-dialog-config' since it isn't a known property of ' ...

What is the proper way to utilize setTimeout in TypeScript?

Let's take a look at an example of how to use setTimeout in Angular and TypeScript: let timer: number = setTimeout(() => { }, 2000); However, upon compilation, you may encounter the following error message: Error TS2322: Type 'Timeout' ...

Refine current attributes of an object in Typescript

In typescript, I have an object of type any that needs to be reshaped to align with a specific interface. I am looking for a solution to create a new object that removes any properties not defined in the interface and adds any missing properties. An exam ...

Error Encountered: Unable to access property 'cars' as it is undefined in Angular Material Table

I'm encountering an issue with the Angular Material Table (Angular Material Table) After using ng generate @angular/material:material-table --name=car-table to create the default angular table, everything works fine. However, when I attempt to injec ...

Implementing the TabView positioning at the top for IOS in Nativescript

Is it possible to place the TabView at the top on IOS rather than the bottom? ...

Using TypeScript to transform a tuple type into an object

When dealing with a tuple type like: [session: SessionAgent, streamID: string, isScreenShare: boolean, connectionID: string, videoProducerOptions: ProducerOptions | null, connection: AbstractConnectionAgent, appData: string] there is a need to convert it ...

Using Angular, implementing conditional statements within a for loop

I am currently working on a project where I have an array being looped inside a tag, using the target="_blank" attribute. The issue is that one of the elements in the array should not have this target="_blank" attribute. What would be the best course of ...

Update the input value with the selected option from the dropdown menu in Angular

How can I dynamically set the value of an input field based on the selection from a dropdown menu in Angular using Reactive Forms? Below is my HTML code: <nb-card> <nb-card-header> Services </nb-card-header> <nb-card-body&g ...

Encountering an error while trying to run ng serve following ng build

Currently working on my initial Angular application, I am in the process of setting up an existing Angular app on my local machine. Encountered the following error message when running ng serve ERROR in src/app/common-componets/directives/dropFile/d ...

The data fails to display on the template in Angular4/MEAN environment

I am currently learning the MEAN stack with Angular4 and have encountered a problem. I am using a service to fetch data from node.js, which is then subscribed by the app.component component. Although logging the result shows the correct output, displaying ...

How can I incorporate the LIKE operator in a query when dealing with PostgreSQL's String array type using TypeORM?

My database backend is PostgreSQL and I have a TypeORM object simplified as follows: @Entity() @Index(['name'], {unique: true}) export class Foo extends BaseEntity { @PrimaryGeneratedColumn('uuid') id: string; @Column() name: st ...

Retrieve the name of a property or field from an object with a specified type

I have an angular class that is injectable with a readonly property. I do not have control over the initialization of this class as it is meant to be used in a library. Consumers of this library can access these properties but are not allowed to modify the ...

Creating HTML content from a function return in Angular

I'm trying to figure out the process through which TypeScript and HTML exchange data. (TypeScript) public getContactByTradingPartnerId(tradingPartnerId: number):string { const map = { 1001 : "<a href="/cdn-cgi/l/email-protection ...

There is no initial value set for the property and it is not definitively assigned in the constructor

I encountered an issue while working on the following code snippet: export class UserComponent implements OnInit { user: User; constructor() { } ngOnInit() { this.user = { firstName : "test", lastName ...

Conceal mat-table column when form field is empty

As a newcomer to the world of programming, I am currently tackling a table that includes form fields for filtering purposes. My goal is to dynamically hide or show table columns based on whether a form field has a value or not. In my table.component.ts ...

How can I properly prevent the use of a nested observable subscription within a loop?

Utilizing Angular2 along with Firebase through Angularfire2 to retrieve data from a Firebase Realtime Database, which essentially consists of a large JSON object. The current setup involves a polling system where polls are stored in a 'Polls' no ...

Looking for a sublime plugin that will enhance your angular view template?

When using Sublime Text with Angular (2/4), everything works great until I'm working in the view template file. The interpolation doesn't offer auto-completion for class properties that support the view, unlike what I've seen in VS Code. Ar ...

Achieving selective exclusion of specific keys/values while iterating through an array and rendering them on a table using Angular

Currently facing a hurdle and seeking advice I am developing an angular application that fetches data from an API and presents it on the page The service I am utilizing is named "Api Service" which uses HTTPClient to make API calls apiservice.service.ts ...

The requested page for angular-in-memory-web-api could not be located within the Angular 4.2.2 CLI web-api functionality

Currently, I am delving into the Angular framework (specifically version 4.2.2) and going through the Tour of Heroes tutorial. As I progressed to the HTTP section, the tutorial introduced the use of angular-in-memory-web-api to simulate a web api server. ...