5

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

            })
       })

2 Answers 2

7

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

Sign up to request clarification or add additional context in comments.

4 Comments

thanks your answer. got this error : Uncaught TypeError: Illegal invocation
@SoheilAlizadeh, oops, accidently made the false a string and not the actual boolean value false. Simply remove the quotes around false, updated answer to reflect
How does one access the respective fields?
@user8016906 that would depend on the backend and how it parses requests. Specifically for asp I do not know as I've never used it.
1

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)
{
    ....
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.