skip to Main Content

I’m building an app with Expo Go where I use the expo-camera library.
It works fine when testing it on the Emulator in Android Studio, but when using the Expo Go app on an iPhone, I don’t receive the picture on the backend.

The code for taking the picture:

  takePicture = async () => {
    if (cameraRef.current) {
      console.log("Taking picture");
      const options = { quality: 0.7, base64: true };
      const data = await cameraRef.current.takePictureAsync(options);
      const source = data.base64;
      if (source) {
        // Save the photo to the backend including information from params
        try{
          let base64Img = `data:image/jpg;base64,${source}`;
          await logPicture(local, base64Img);
        }catch(error){
          console.error("Error saving photo to backend", error);
        }
      }
    }
  };

The logPicture function in React native

export async function logPicture(local, image) {
  const auth = getAuth();
  //Get the token
  console.log("Image", image);
  const token = await auth.currentUser.getIdToken();
  return fetch(apiServerUrl + '/logbook/picture', {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`,
      'maxBodyLength': 20000000,
      'maxContentLength': 20000000,
      'maxHttpBufferSize': 1e8 
    },
    body: JSON.stringify(local, image)
  })
  .then((response) => {
    console.log("Response from backend", response);
    return response.json();
  });
}

I can see the base64 string is being generated, in both the emulator and Expo Go client but on the backend (nodejs) the body only contains data from the Local parameter, when taking a picture with the Expo Go client.

Backend code:

router.post("/picture", upload.single('photo'), checkIfAuthenticated, (req, res) => {
  try{
    console.log(req.body);
    //Get the photo as base54String and save it to the filesystem
    var base64String = req.body.photo;
    //Remove the header from the base64 string
    var base64Image = base64String.split(';base64,').pop();
    //Write the file to the uploads folder
    var filename = path.join(__dirname, "../../uploads/" + req.authId + "_" + Date.now() + ".png");
    require("fs").writeFile(filename, base64Image, {encoding: 'base64'}, function(err) {
      if(err){
        console.log(err);
      }else{
        console.log('File created');
      }
    });
    res.status(200);
    res.send("ok");
  }catch(e){

  }
});

Any idea why it works in the emulator but not with Expo Go?

2

Answers


  1. Chosen as BEST ANSWER

    Found the error. The emulator posted a default picture of 19,7 KB which was under the default limit of Express. That led to the picture being processed correctly. When taking the picture with Expo Go, the size is around 1,2 MB which is above the default size limit of Express.

    Adding these to lines to the Express middleware, did the trick:

    app.use(express.json({ limit: '50mb' }));
    app.use(express.urlencoded({ extended: true }));
    

  2. You don’t need to pass base64 string as second parameter in JSON.stringify

    body: JSON.stringify(local, image) // ❌
    

    Everything you need to stringify and sent to backend will be on first parameter which is an object, so we can change that to like this

    body: JSON.stringify(
      {
        ...local,
        photo: image
      }
    ) //✅
    

    So the function will look like

    export async function logPicture(local, image) {
      const auth = getAuth();
      //Get the token
      console.log("Image", image);
      const token = await auth.currentUser.getIdToken();
      return fetch(apiServerUrl + '/logbook/picture', {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${token}`,
          'maxBodyLength': 20000000,
          'maxContentLength': 20000000,
          'maxHttpBufferSize': 1e8 
        },
        body: JSON.stringify(
          {
            ...local,
            photo: image
          }
        )
      })
      .then((response) => {
        console.log("Response from backend", response);
        return response.json();
      });
    }
    

    JSON stringify docs

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search