Can someone help me figure out why when Im trying to upload a csv file, the data=[object FormData]?

Here is how I do my request in ReactJs:

export const uploadNewParticipant = createAsyncThunk(
  async ({ userId, projectId, withMail, file }: IProjectNewParticipantsCsv & IAppLoaderAction) => {
    const formData = new FormData();

    const data = {};
    data["userId"] = userId.toString();
    data["withMail"] = withMail.toString();

    if (projectId) {
      data["projectId"] = projectId.toString();

    formData.append("data", JSON.stringify(data));
    formData.append("files", file,;

    const response = await<Array<IProjectGroupElement>>(`${apiUrls.csv.add}`, formData, {
      headers: {
        "Content-Type": "multipart/form-data",

    return { data: (await response).data };

And in strapi v4 I have this:

customController.addEndusersCsv = async (ctx) => {
    const files = ctx.request.files;

    console.log("ctx.request.files: ", ctx.request.files);
    console.log("ctx.request.body: ", ctx.request.body);
    console.log(" ",;

    const data =;

    const { userId, projectId, withMail } = data;
    console.log("Parsed data:", userId, projectId, withMail);
    console.log("Files:", files);

Here is the logs that strapi gives me:

ctx.request.files:  {}
ctx.request.body:  { data: '[object FormData]' }  [object FormData]
Parsed data: undefined undefined undefined
Files: {}

Why = [object FormData]???

This topic has been created from a Discord post (1219667770912804944) to give it more visibility.
It will be on Read-Only mode here.
Join the conversation on Discord

You don’t have access directly to it. I am not sure of the work around. I typically just use the upload provider rather then creating a custom upload controller. But this is a commonly asked question will be great to figure out how to accomplish this in a custom controller.