Creating multipart/form-data with varying Content-Types for each part using JavaScript (or Angular)

Apologies for the confusion, please refer to my update below

I have a requirement to link my AngularJS Project with an existing RESTful API. This API uses POST requests that involve uploading a file and submitting form data in a request. However, one of the form inputs needs to be in JSON format under the Content-Type: Application/json.

Upon researching online, I found that I can only use POST with Content-Type: multipart/form-data, where each part does not have a specific MIME type. How do I construct my multipart/form-data with different MIME types for each part using JavaScript?

POST /api/v1/inventory
Host: localhost:8000
Origin: http://localhost:9000
Content-Type: multipart/form-data; boundary=------border

------border
Content-Disposition: form-data; name="owner"

john doe
------border
Content-Disposition: form-data; name="image"; filename="mybook.png"
Content-Type: image/png


------border
Content-Disposition: form-data; name="items"
Content-Type: application/json

{"name": "Book", "quantity": "12"}
------border--

Useful Resources:

  1. https://developer.mozilla.org/en-US/docs/Web/Guide/Using_FormData_Objects
  2. REST - HTTP Post Multipart with JSON
  3. application/x-www-form-urlencoded or multipart/form-data?

Update

I realized I posed the wrong question initially. The actual issue is related to how the server processes the POST request:

func POST(req):
     owner = req.owner // This is string
     image = req.image // This is file object
     itemQuantity = req.items.quantity // Items is an object with attribute quantity
     itemName = req.items.name // Items is an object with attribute name

I have since figured out the solution to submitting this post request correctly. I will share my answer shortly.

Once again, I apologize for the confusion caused by the initial question.

Answer №1

In line with the guidelines outlined on the FormData documentation, a specific content type can be appended to a field by utilizing the Blob constructor:

var formData = new FormData();

formData.append('items', new Blob([JSON.stringify({
    name: "Book",
    quantity: "12"
})], {
    type: "application/json"
}));

Upon closer examination, it has been observed that the transmission of the data occurs in the following manner:

Content-Disposition: form-data; name="items"; filename="blob"
Content-Type: text/json

The only alternative, aside from manually constructing the entire request, is to provide a string value instead:

formData.append('items', '{"name": "Book", "quantity": "12"}');

Regrettably, this method does not include setting the Content-Type header.

Answer №2

One of the common mistakes I made was assuming that the items needed to be in JSON format in order for us to access its attributes.

Fortunately, sending a multipart request that includes both a file and an object is actually quite straightforward.

form = new FormData();
form.append('items[name]', 'Book');
form.append('items[quantity]', 12);
form.append('image', imageFile);
form.append('owner', 'John Doe');

This means that the request header and body will appear something like this:

POST /api/v1/inventory
Host: localhost:8000
Origin: http://localhost:9000
Content-Type: multipart/form-data; boundary=------border

------border
Content-Disposition: form-data; name="owner"

john doe
------border
Content-Disposition: form-data; name="image"; filename="mybook.png"
Content-Type: image/png


------border
Content-Disposition: form-data; name="items[name]"

Book
------border
Content-Disposition: form-data; name="items[quantity]"

12
------border--

Answer №3

Only when I made the pivotal change of setting the Content-Type header to undefined did everything fall into place, allowing me to successfully post a file along with some JSON data.

public uploadFile(code: string, file):angular.IHttpPromise<any>{
    var data = `{"query":"mutation FIRMSCORECARD_CALCULATE($code:String!){ FirmScorecardMutation{ BatchCalculate(Code:$code) }}","variables":{"code":"${code}"},"operationName":"FIRMSCORECARD_CALCULATE"}`;
    var formData = new FormData();
    formData.append('operations', data);
    formData.append('file', file, file.name);

    let config = {
        headers: {
            'Accept': 'application/json',
            'Content-Type': undefined
        }
    };
    let response = this.$http.post(this.graphqlUrl, formData, config);
    return response;
}

Answer №4

Give this a shot.

protected void AddFormDataToContent(object data, MultipartFormDataContent content,string baseName)

{ var properties = data.GetType().GetProperties(); foreach (PropertyInfo property in properties) { var propertyValue= property.GetValue(data, null); if (propertyValue != null) { var propertyType= propertyValue?.GetType(); if (propertyType.Namespace!="System" && !propertyType.IsEnum) { AddFormDataToContent(propertyValue, content, $"{baseName}.{property.Name}"); } else { content.Add(new StringContent(propertyValue?.ToString()), $"{baseName}.{property.Name}"); } }

}

}

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

Transferring identification data between views within an application (AngularJS, NodeJs, HTML)

I'm working on an HTML page that lists users from MongoDB. The page allows for deleting and updating users. I am encountering an issue with the update button - I want a new HTML page to appear with a form when the button is clicked, capturing the user ...

When scrolling, a new page loads seamlessly

Recently, I came across a website that has an interesting feature where new content is loaded automatically while scrolling, seamlessly appending to the existing page. What's more fascinating is that not only does the content change, but the URL also ...

Issue: "A 'reflect-metadata shim is needed' error occurs during the transition to Webpack 2"

My team and I are facing a challenge as we try to upgrade our code base to Webpack 2. Currently, we're encountering two stubborn errors: 'Uncaught reflect-metadata shim is required when using class decorators' and 'Cannot read property ...

Disable the resizing and responsiveness features in the jQuery Basic Slider

I'm currently utilizing the Basic jQuery Slider from the Basic Slider website, and I am attempting to eliminate the responsive/resize feature. My goal is to keep the slider contained within a centered div without changing its size. However, whenever I ...

Telegram: verification key mismatch detected

I am currently facing an issue with implementing a Telegram PHP example using JavaScript. The hashes do not match, even after running the example's php code which also resulted in failure with identical hashes. I have tried adjusting my bot settings b ...

Adjusting the width of a select box to match the size of its child table using CSS

Within my Vue application, I've implemented a select box that contains a table component. When the select box is clicked, the table becomes visible in a container. However, I'm facing an issue where I can't dynamically adjust the width of th ...

What is the best way to include a select HTML element as an argument in an onSubmit form function call?

I am currently facing an issue where I am attempting to pass HTML elements of a form through the submit function as parameters. I have been able to successfully retrieve the nameInput element using #nameInput, but when trying to access the select element ( ...

The process of automating e-signature input with Selenium

Is there a way to automate e-signature input in Selenium? I attempted using the action class to draw a line on the canvas object. Below is the code I used: Actions actionBuilder=new Actions(driver); Action drawOnCanvas=actionBuilder ...

Chai spy does not recognize sinon stubbed functions when verifying function calls

I am working with two asynchronous functions that return bluebird promises: Async1: function() { return new Promise(function(resolve, reject) { execute(query) .then(function(resp) { resolve(resp); }) .catch(function(err) { ...

What is the best way to call a JavaScript function within a PHP echo statement that outputs a <div> element?

Having trouble echoing this PHP code due to issues with single quotes, causing the HTML to end prematurely. Any suggestions on how to fix this? function button($conn){ $sql = "SELECT * FROM table"; $result= mysqli_query($conn, $sql); while($r ...

What is the reason behind div elements shifting when hovering over a particular element?

Currently, I have floated all my div elements (icons) to the left and margin-lefted them to create space in between. I've displayed them inline as well. However, when I hover over one element (icon), the rest of the elements move. Can you please help ...

Validate that a string is a correct file name and path in Angular without using regular expressions

Currently, I am using regex to determine if a string is a valid file name and path. However, when the string length becomes longer, it ends up consuming a significant amount of CPU, resulting in browser performance issues. public static readonly INVALID_F ...

What is preventing me from passing a JSON array as data in a GET request using jQuery Ajax?

When sending a get request like the one below: $.ajax({ url: 'http://localhost:8000/api/points/', contentType:"application/json", dataType: "json", data: JSON.stringify({"content_type":content_type,"object_id":object_id}), t ...

Discovering the Nearest Textfield Value Upon Checkbox Selection Using JQuery

How can I retrieve the value of the nearest Textfield after selecting a checkbox? This HTML snippet serves as a simple example. In my actual project, I have dynamically generated lists with multiple checkboxes. I require a way to associate each checkbox wi ...

Send back alternate HTML content if the request is not made via AJAX

Last time I asked this question, I received several negative responses. This time, I will try to be more clear. Here is the structure of a website: Mainpage (Containing all resources and scripts) All Other pages (HTML only consists of elements of that ...

The Ajax script triggers the PHP script twice

Utilizing AJAX on my HTML page, I am able to dynamically load data from a MySQL database without reloading the page and send email notifications upon certain events. The process involves Ajax calls to script.php which then makes requests to the database an ...

Tips for removing information from a nested array that aligns with an ID in a separate array

Can anyone assist me with removing a nested array that matches the id of the main array? Here is arrayOne: [ { "id": "1", "role": [ "pos_cashier_1", "pos_manager" ...

Choosing a single radio button value within a nested ng-repeat loop in AngularJS

Help needed with selecting only one radio button value in nested ng-repeat. Please review the source code and suggest any potential mistakes. <form ng-submit="save()"> <div ng-repeat="x in surveyLst"> <div class="row"> < ...

Can one showcase a php content using an ajax event?

I’m having trouble asking the right question because I’m not sure what I’m doing. I have a form that includes a default PHP script that creates three different lines: <form method="GET" name="NewDeliveryNote" action="ItemPosts_INSERT.php"> < ...

Reset jQuery validation when a button is clicked

I need assistance with a form validation issue. I am using jQuery validation methods to validate the controls on my form. However, I am facing difficulties in clearing the validation when clicking on 'cancel'. Below is the code snippet: <scr ...