0



I’m trying to send a multipart/form-data request to the Google Drive API from my React Native app.
When I use Postman, the request works perfectly, but when I try to implement the same request in React Native using fetch or axios, I keep getting a "Malformed multipart body" error.

I’m constructing the request using FormData, adding metadata (metadata) and the file (file).
This setup works fine in Postman, so I suspect there’s something different in how React Native handles FormData or the Content-Type header for multipart requests.

Has anyone experienced this issue in React Native?
Is there a specific way to configure FormData to behave the same way as it does in Postman?
Or, if you have any recommendations for alternative approaches to send multipart/form-data requests from React Native, I’d really appreciate the guidance.

Thanks in advance for any help!

enter image description here

export const uploadToGoogleDrive = async (data) => {
  try {
    const accessToken = await signInWithGoogle();
    const fileName = data.title;
    const fileDescription = data.description;
    const file = data.file;
    const fileMimeType = file.assets[0].mimeType;

    const formData = new FormData();

    formData.append("metadata", JSON.stringify({
      name: fileName,
      mimeType: fileMimeType,
      description: fileDescription,
      parents: [GOOGLE_DRIVE_FOLDER_ID]
    }), { type: 'application/json' });

    formData.append('file', {
      uri: file.assets[0].uri,
      type: fileMimeType,
      name: fileName,
    });

    const response = await fetch(`${GOOGLE_DRIVE_ENDPOINT}/files?uploadType=multipart`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
      },
      body: formData,
    });

    if (!response.ok) {
      const errorText = await response.json();
      console.log("Detailed Error:", errorText);
      throw new Error(`Error uploading file: ${response.statusText}, details: ${errorText}`);
    }

    return response;

  } catch (error) {
    console.error("Upload error:", error);
    if (error.response) {
      console.error("Response data:", error.response.data);
    } else if (error.request) {
      console.error("Request details:", error.request);
    } else {
      console.error("Error:", error.message);
    }
  }
};

1 Answer 1

1

Unfortunately, I couldn't understand that in your showing script, which you are using FormData and fetch of the native node.js or of other packages. From { type: 'application/json' }, I guessed that you might be using FormData and fetch of the native node.js. If my understanding is correct, how about the following modification?

In this modification, it supposes that file.assets[0].uri is the file path. Please be careful about this. If it's the direct link of the URL, please modify the script.

Also, this modification supposes that GOOGLE_DRIVE_FOLDER_ID and GOOGLE_DRIVE_ENDPOINT have already been declaread, and your access token accessToken is valid for uploading the file. Also, please be careful about this.

Modified script:

In this modification, const fs = require("fs"); is required to be loaded.

export const uploadToGoogleDrive = async (data) => {
  try {
    const accessToken = await signInWithGoogle();
    const fileName = data.title;
    const fileDescription = data.description;
    const file = data.file;
    const fileMimeType = file.assets[0].mimeType;

    const formData = new FormData();

    formData.append(
      "metadata",
      new Blob(
        [
          JSON.stringify({
            name: fileName,
            mimeType: fileMimeType,
            description: fileDescription,
            parents: [GOOGLE_DRIVE_FOLDER_ID],
          }),
        ],
        { type: "application/json" }
      )
    );

    formData.append("file", await fs.openAsBlob(file.assets[0].uri, { type: fileMimeType }));

    const response = await fetch(`${GOOGLE_DRIVE_ENDPOINT}/files?uploadType=multipart`, {
        method: "POST",
        headers: { Authorization: `Bearer ${accessToken}` },
        body: formData,
      }
    );

    if (!response.ok) {
      const errorText = await response.json();
      console.log("Detailed Error:", errorText);
      throw new Error(`Error uploading file: ${response.statusText}, details: ${errorText}`);
    }
    return response;

  } catch (error) {
    console.error("Upload error:", error);
    if (error.response) {
      console.error("Response data:", error.response.data);
    } else if (error.request) {
      console.error("Request details:", error.request);
    } else {
      console.error("Error:", error.message);
    }
  }
};
  • When I tested this modified script using my valid access token and a sample file, I confirmed that the file could be correctly uploaded.
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for the response! I'm using React Native, not Node.js, so I don't have access to the fs module. I’ve tried both react-native-fs and Expo’s File System, and my file path looks like this: file:///data/user/0/com.myApp/cache/imageName.jpg, but the upload still isn’t working. Do you have any advice for handling file uploads to Google Drive in React Native without Node-specific modules?
@Alexa Thank you for replying. About I don't have access to the fs module., although I'm not sure whether I could correctly understand your situation, how about modifying my script from formData.append("file", await fs.openAsBlob(file.assets[0].uri, { type: fileMimeType })); to formData.append('file', { uri: file.assets[0].uri, type: fileMimeType, name: fileName });?
@Alexa In order to upload the data to Google Drive, the file content is required to be used. If this modification is not useful, in your situation, can I ask you about the method for retrieving the content from a file from a file path of file.assets[0].uri?

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.