DEV Community

Cover image for Uploading Images to Cloudinary in React Native Using Cloudinary's API
Joy Palumbo
Joy Palumbo

Posted on

Uploading Images to Cloudinary in React Native Using Cloudinary's API

It is very common to allow a user to upload a photo in a given application and can make an application more dynamic and interactive. Today we are going to talk about how to allow a user to upload an image to Cloudinary using Cloudinary's API and how to retrieve that image from Cloudinary. When trying to include Cloudinary in my application, I was running into issues with Cloudinary not accepting the file uploaded from Expo. I could not find very much helpful documentation on line so I'm hoping this tutorial will help others who run into the same issue as I did.

The first thing you will want todo is install Expo's ImagePicker. You can do this by entering the following code into your terminal.

expo install expo-image-picker

In any file that you wish to allow a user to upload a file, you will need to import ImagePicker at the top.

import * as ImagePicker from 'expo-image-picker';

Next we will write a function. Most of this code can be found in Expo's docks but I have included some extra code. The file type that image picker normal supplies is not the correct format for Cloudinary so I had to modify Expo's code a little bit so that Cloudinary would accept the file.

I started with declaring a variable to contain the url for Cloudinary's API.

In the Cloudinary Dashboard the first line is your cloudinary name. You will want to insert that into the cloudinayry url as seen in the code snippet below the cloudinary image. You do not need the curly brackets around your cloudinary name.

Alt Text

let CLOUDINARY_URL = 'https://api.cloudinary.com/v1_1/{insert your cloudinary name here}/upload';

When using the Cloudinary API we don't need to use the API key, secret or environment variable. You will need an upload preset. Go to your Cloudinary Dashboard. Go to Settings. Once you are on your settings page, go to the "upload" tab. Scroll down to "upload presets". You will need to change the settings to "unsigned". This will then supply you with the upload preset that you need. You can either create a variable for it like we did for the cloudinary url but in my example I plugged it directly inside the function.

Now let's write the function! I will provide seudo code for each line explaining what each part does.

//allows user to upload a photo

  //asks phone for permission to access photos

  let openImagePickerAsync = async () => {
    let permissionResult = await ImagePicker.requestCameraRollPermissionsAsync();

//this tells the application to give an alert if someone doesn't allow //permission.  It will return to the previous screen.

    if (permissionResult.granted === false) {
      alert('Permission to access camera roll is required!');
      return;
    }

 //This gets image from phone

    let pickerResult = await ImagePicker.launchImageLibraryAsync({
      allowsEditing: true,
      aspect: [4, 3],

//We need the image to be base64 in order to be formatted for Cloudinary

      base64: true
    });

//this just returns the user to the previous page if they click "cancel"

    if (pickerResult.cancelled === true) {
      return;
    }

    //sets image from imagePicker to SelectedImage.
//This is if you are using hooks. The hook for this I have set up as:
//[selectedImage, setSelectedImage] = useState("").  If you're using //anclass component you can use setState here.  This file format will be
//a file path to where the image is saved.  

    setSelectedImage({ localUri: pickerResult.uri });

    //***IMPORTANT*** This step is necessary.  It converts image from //file path format that imagePicker creates, into a form that cloudinary //requires. 

    let base64Img = `data:image/jpg;base64,${pickerResult.base64}`;

// Here we need to include your Cloudinary upload preset with can be //found in your Cloudinary dashboard. 

    let data = {
      "file": base64Img,
      "upload_preset": "insert your upload preset here,within quotations",
    }

    //sends photo to cloudinary
//**I initially tried using an axios request but it did NOT work** I was 
//not able to get this to work until I changed it to a fetch request.

    fetch(CLOUDINARY_URL, {
      body: JSON.stringify(data),
      headers: {
        'content-type': 'application/json'
      },
      method: 'POST',
    }).then(async r => {
      let data = await r.json()

//Here I'm using another hook to set State for the photo that we get back //from Cloudinary

     setPhoto(data.url);
    }).catch(err => console.log(err))
  };
Enter fullscreen mode Exit fullscreen mode

We data we get back from Cloudinary will look similar to this. It can be saved as a string your database.

http://res.cloudinary.com/dary8ct/image/upload/v1580507361/fudyliwx7nxiezux561n.jpg
Enter fullscreen mode Exit fullscreen mode

To render the photo in Expo, within your return section you can include this:

return (
<Text> Look at our pretty picture! </Text>
      <Image source={{ uri: "http://res.cloudinary.com/dary8ct/image/upload/v1580507361/fudyliwx7nxiezux561n.jpg" }} style={{ width: 150, height: 150 }} />}

)
Enter fullscreen mode Exit fullscreen mode

Below is the code without seudo code:

import React, { useState, useContext } from 'react';
import * as ImagePicker from 'expo-image-picker';

export default function Photo(props) {
  let CLOUDINARY_URL = 'https://api.cloudinary.com/v1_1/{insert your cloudinary name here}/upload';


  let openImagePickerAsync = async () => {
    let permissionResult = await ImagePicker.requestCameraRollPermissionsAsync();
    if (permissionResult.granted === false) {
      alert('Permission to access camera roll is required!');
      return;
    }

    let pickerResult = await ImagePicker.launchImageLibraryAsync({
      allowsEditing: true,
      aspect: [4, 3],
      base64: true
    });

    if (pickerResult.cancelled === true) {
      return;
    }

    setSelectedImage({ localUri: pickerResult.uri });

    let base64Img = `data:image/jpg;base64,${pickerResult.base64}`;

    let data = {
      "file": base64Img,
      "upload_preset": "insert your upload preset here,within quotations",
    }

    fetch(CLOUDINARY_URL, {
      body: JSON.stringify(data),
      headers: {
        'content-type': 'application/json'
      },
      method: 'POST',
    }).then(async r => {
      let data = await r.json()

      setPhoto(data.url);
    }).catch(err => console.log(err))
  };

  return (
    <View>
      <Text> Look at our pretty picture! </Text>
      <Image source={{ uri: "http://res.cloudinary.com/dary8ct/image/upload/v1580507361/fudyliwx7nxiezux561n.jpg" }} style={{ width: 150, height: 150 }} />}

</View>
  );
}
Enter fullscreen mode Exit fullscreen mode

Hopefully this tutorial helped in allowing your application to upload photos to Cloudinary and display those images within your app!

Top comments (2)

Collapse
 
malachaifrazier profile image
Malachai

If the user declines permissions when asked, is there an elegant way to ask again?

Collapse
 
bernardbaker profile image
Bernard Baker

It's a lot simpler in React Native than it is when using that API with hooks and React Admin.