How to use FormData in react-native?

Here is my simple code FormData with react-native to post request with string and image.

I have used react-native-image-picker to capture/select photo react-native-image-picker

let photo = { uri: source.uri}
let formdata = new FormData();

formdata.append("product[name]", 'test')
formdata.append("product[price]", 10)
formdata.append("product[category_ids][]", 2)
formdata.append("product[description]", '12dsadadsa')
formdata.append("product[images_attributes[0][file]]", {uri: photo.uri, name: 'image.jpg', type: 'image/jpeg'})

NOTE you can change image/jpeg to other content type. You can get content type from image picker response.

fetch('http://192.168.1.101:3000/products',{
  method: 'post',
  headers: {
    'Content-Type': 'multipart/form-data',
  },
  body: formdata
  }).then(response => {
    console.log("image uploaded")
  }).catch(err => {
    console.log(err)
  })  
});

This worked for me

var serializeJSON = function(data) {
  return Object.keys(data).map(function (keyName) {
    return encodeURIComponent(keyName) + '=' + encodeURIComponent(data[keyName])
  }).join('&');
}

var response = fetch(url, {
  method: 'POST',
  body: serializeJSON({
    haha: 'input'
  })
});

If you want to set custom content-type for formData item:

var img = {
    uri : 'file://opa.jpeg',
    name: 'opa.jpeg',
    type: 'image/jpeg'
};
var personInfo = {
    name : 'David',
    age: 16
};

var fdata = new FormData();
fdata.append('personInfo', {
    "string": JSON.stringify(personInfo), //This is how it works :)
    type: 'application/json'
});

fdata.append('image', {
    uri: img.uri,
    name: img.name,
    type: img.type
});

Providing some other solution; we're also using react-native-image-picker; and the server side is using koa-multer; this set-up is working good:

ui

ImagePicker.showImagePicker(options, (response) => {
      if (response.didCancel) {}
      else if (response.error) {}
      else if (response.customButton) {}
      else {
        this.props.addPhoto({ // leads to handleAddPhoto()
          fileName: response.fileName,
          path: response.path,
          type: response.type,
          uri: response.uri,
          width: response.width,
          height: response.height,
        });
      }
    });

handleAddPhoto = (photo) => { // photo is the above object
    uploadImage({ // these 3 properties are required
      uri: photo.uri,
      type: photo.type,
      name: photo.fileName,
    }).then((data) => {
      // ...
    });
  }

client

export function uploadImage(file) { // so uri, type, name are required properties
  const formData = new FormData();
  formData.append('image', file);

  return fetch(`${imagePathPrefix}/upload`, { // give something like https://xx.yy.zz/upload/whatever
    method: 'POST',
    body: formData,
  }
  ).then(
    response => response.json()
  ).then(data => ({
    uri: data.uri,
    filename: data.filename,
  })
  ).catch(
    error => console.log('uploadImage error:', error)
  );
}

server

import multer from 'koa-multer';
import RouterBase from '../core/router-base';

const upload = multer({ dest: 'runtime/upload/' });

export default class FileUploadRouter extends RouterBase {
  setupRoutes({ router }) {
    router.post('/upload', upload.single('image'), async (ctx, next) => {
      const file = ctx.req.file;
      if (file != null) {
        ctx.body = {
          uri: file.filename,
          filename: file.originalname,
        };
      } else {
        ctx.body = {
          uri: '',
          filename: '',
        };
      }
    });
  }
}

Usage of formdata in react-native

I have used react-native-image-picker to select photo. In my case after choosing the photp from mobile. I'm storing it's info in component state. After, I'm sending POST request using fetch like below

const profile_pic = {
  name: this.state.formData.profile_pic.fileName,
  type: this.state.formData.profile_pic.type,
  path: this.state.formData.profile_pic.path,
  uri: this.state.formData.profile_pic.uri,
}
const formData = new FormData()
formData.append('first_name', this.state.formData.first_name);
formData.append('last_name', this.state.formData.last_name);
formData.append('profile_pic', profile_pic);
const Token = 'secret'

fetch('http://10.0.2.2:8000/api/profile/', {
    method: "POST",
    headers: {
      Accept: "application/json",
      "Content-Type": "multipart/form-data",
      Authorization: `Token ${Token}`
    },
    body: formData
  })
  .then(response => console.log(response.json()))