Send file with JSON Data in ajax request

16,052

Solution 1

You do not put the FormData instance within an object and stringify it. You do the opposite: put your file(s) and other data in the FormData instance.

And as the answer you linked to says change the contentType and processData options to false to tell jQuery not to process the data itself.

var file_data = $("#Image").prop("files")[0];   
var fd = new FormData();

fd.append("file", file_data);
fd.append("isFirst", true);
fd.append("ExternalProjects", ExternalProjects);
$.ajax({
    url: '@postUrl',
    method: "POST",
    contentType: false,
    processData: false,
    data:fd
});

Your data will be in the respective fields: file, isFirst, and ExternalProjects

Solution 2

The best wat I discovered for myself:

export const convertDataToFormDataFormat = (data, formData = null, keyPrefix = '') => {
  if (!data) {
    return null;
  }

  let currentFormData = formData || new FormData();
  if (Array.isArray(data)) {
    data.forEach((entry, i) => {
      currentFormData = convertDataToFormDataFormat(entry, currentFormData, `${keyPrefix}[${i}].`);
    });

    return currentFormData;
  }

  if (data) {
    Object.entries(data).forEach(([key, value]) => {
      const fullKey = keyPrefix + key;
      if (value === undefined || value === null) {
        currentFormData.append(fullKey, '');
      } else if (value.constructor === File) {
        currentFormData.append(fullKey, value);
      } else if (Array.isArray(value)) {
        currentFormData = convertDataToFormDataFormat(value, currentFormData, `${fullKey}`);
      } else if (value === Object(value)) {
        currentFormData = convertDataToFormDataFormat(value, currentFormData, `${fullKey}.`);
      } else {
        currentFormData.append(fullKey, value);
      }
    });
  }

  return currentFormData;
};

Converts to something like this:

fieild.test1= 'test';
fieild.test2= 'test';
field.arr[0].testField1 = 'testField ';
field.arr[0].testField2 = 'testField ';
field.arr[1].testField = 'testField ';
field.arr[1].testField2 = 'testField ';
field.arr[2].testField = 'testField ';
field.arr[2].testField2 = 'testField ';

Works great for asp.net core 2.0:

[HttpPost]
public async Task<IActionResult> CreateExpense([FromForm] List<SomeModelWithIFormFileField> dto)
{
    ....
}
Share:
16,052
Soheil Alizadeh
Author by

Soheil Alizadeh

Updated on August 21, 2022

Comments

  • Soheil Alizadeh
    Soheil Alizadeh over 1 year

    I want to send a image file to a the Controller but HttpPostedFileBase is null and I enter image: image outside JSON.stringify({}) but not worked. Also, I change contentTypeand see this question and use it answer but my problem not fixed.

    var file_data = $("#Image").prop("files")[0];   
    var image = new FormData();
    
    image.append("file", file_data);
    
    $.ajax({
            url: '@postUrl',
            method: "POST",
            contentType: 'application/json',
            data:
                JSON.stringify({
                        image: image,
                        isFirst : true,
                        ExternalProjects: ExternalProjects,
                        // more data
    
                })
           })