DEV Community

Dallington Asingwire
Dallington Asingwire

Posted on • Edited on

How to upload an image in React Native

In this post, we are going to learn how to upload an image in a react native app to Laravel api server.
We are going to use react-native-image-crop-picker, a package to handle upload of an image either using camera or from the gallery.
First, we install this package using npm by using the command below;

npm i react-native-image-crop-picker
Enter fullscreen mode Exit fullscreen mode

Hooks takePhotoFromCamera() and choosePhotoFromLibrary()

import React from 'react';
import ImagePicker from 'react-native-image-crop-picker';

const uploadProfilePicture = () => {

const [isUpdatingImage, setIsUpdatingImage] = useState(false);
const [visible, setVisible] = useState(false);

 const takePhotoFromCamera = () => {
       ImagePicker.openCamera({
        width: 300,
        height: 400,
        cropping: true,
        compressImageQuality: 0.7,
      }).then(image => {
        SubmitProfileUpdateDetails(image);
      });
    }


 const choosePhotoFromLibrary = async() => {
      ImagePicker.openPicker({
        width: 300,
        height: 400,
        cropping: true,
      }).then(async (image) => {
        SubmitProfileUpdateDetails(image);
      });
    }
}

}

Enter fullscreen mode Exit fullscreen mode

In the above code snippet, there are two custom hook methods i.e takePhotoFromCamera and choosePhotoFromLibrary.

takePhotoFromCamera() uses openCamera() method on the object imagePicker to allow user upload the photo using camera while choosePhotoFromLibrary() uses openPicker() method on the object imagePicker to allow user upload photo from gallery.

Both hooks call method SubmitProfileUpdateDetails(image) which takes in parameter image (a response object after uploading photo either using camera or from gallery).

Method SubmitProfileUpdateDetails()

var mime = require('mime-types') 
// import this at the top of your component

const SubmitProfileUpdateDetails = async(image) => {

      const imagePath = image.path;
      const mimeType = image.mime;
      const source = {url: image.path};
      const fileExtension = mime.extension(mimeType);
      setImage(imagePath);

      const ImageData = {
        uri: imagePath,
        type: mimeType,
        size: image.size,
        extension: fileExtension,
        name: 'profile_pic',
      }

      let formData = new FormData();
      formData.append('id', profile.user_id);
      formData.append('phone_number',profile.phone_number);
      formData.append('extension', fileExtension);
      formData.append('image', ImageData);

      setIsUpdatingImage(true);
      let result = await uploadProfilePicture(formData);

      const statusCode = result.statusCode;
      const message = result.message;
      if(statusCode == 1){
        const customer = result.data;
        await setProfile(customer);
        await getProfile(customer);
        Toast.show(message);
      }else{
          Alert.alert("Message", message);
      }
      setIsUpdatingImage(false);
      setVisible(false);
    }


Enter fullscreen mode Exit fullscreen mode

The object image has properties; image path and image mime which i use to get image extension. I form object imageData, containing photo details i.e image uri, type, size, extension and name. I use FormData interface to append user data (id, phone number, extension and image object) to the formData object.
Note: I use node package mime-types to get file extension of the uploaded photo. The package can be installed using the command npm i mime-types.

The method calls uploadProfilePicture() which takes in formData object containing user details.

Method uploadProfilePicture()

const uploadProfilePicture = (data) => {
        const endpoint = "change/profile/image";
        return FileUpload(endpoint, data);
   }

Enter fullscreen mode Exit fullscreen mode

Method uploadProfilePicture calls FileUpload which takes in an endpoint "change/profile/image" and user details which are uploaded to the server.
Method FileUpload()

const FileUpload = async(endPoint, data) => {
      const url = config.API_URL+""+ endPoint; 
// Replace config.API_URL with your api url
      const response = await fetch(url, {
        method: 'POST',
        body: data,
        headers: {
          Accept: 'application/json',
          'Content-Type': 'multipart/form-data',
          'authToken': 'yourtokenhere',
        },
      });

      var resultSet;
      (response.ok) 
      ? resultSet = await response.json()
      : resultSet = "HTTP-Error: " + response.status;

      return resultSet;
   }

Enter fullscreen mode Exit fullscreen mode

FileUpload() uses javascript fetch api to send data to the server using Post method.

Full Code


import React from 'react';
import {View, Text,TouchableOpacity} from 'react native';
import FontAwesome from 'react-native-vector-icons/FontAwesome'
import ImagePicker from 'react-native-image-crop-picker';
var mime = require('mime-types')

const uploadProfilePicture = () => {

const [isUpdatingImage, setIsUpdatingImage] = useState(false);
const [visible, setVisible] = useState(false);

 const takePhotoFromCamera = () => {
       ImagePicker.openCamera({
        width: 300,
        height: 400,
        cropping: true,
        compressImageQuality: 0.7,
      }).then(image => {
        SubmitProfileUpdateDetails(image);
      });
    }


 const choosePhotoFromLibrary = async() => {
      ImagePicker.openPicker({
        width: 300,
        height: 400,
        cropping: true,
      }).then(async (image) => {
        SubmitProfileUpdateDetails(image);
      });
    }
}

const SubmitProfileUpdateDetails = async(image) => {
      const imagePath = image.path;
      const mimeType = image.mime;
      const source = {url: image.path};
      const fileExtension = mime.extension(mimeType);
      setImage(imagePath);

      const ImageData = {
        uri: imagePath,
        type: mimeType,
        size: image.size,
        extension: fileExtension,
        name: 'profile_pic',
      }

      let formData = new FormData();
      formData.append('id', profile.user_id);
      formData.append('phone_number',profile.phone_number);
      formData.append('extension', fileExtension);
      formData.append('image', ImageData);

      setIsUpdatingImage(true);
      let result = await uploadProfilePicture(formData);

      const statusCode = result.statusCode;
      const message = result.message;
      if(statusCode == 1){
        const customer = result.data;
        await setProfile(customer);
        await getProfile(customer);
        Toast.show(message);
      }else{
          Alert.alert("Message", message);
      }
      setIsUpdatingImage(false);
      setVisible(false);
    }

const FileUpload = async(endPoint, data) => {
      const url = config.API_URL+""+ endPoint; 
      const response = await fetch(url, {
        method: 'POST',
        body: data,
        headers: {
          Accept: 'application/json',
          'Content-Type': 'multipart/form-data',
          'authToken': 'yourtokenhere',
        },
      });

      var resultSet;
      (response.ok) 
      ? resultSet = await response.json()
      : resultSet = "HTTP-Error: " + response.status;

      return resultSet;
   }

 return(

            <View>
            <View>
            <Text>Upload Profile Photo</Text>
            <Text>Choose Your Profile Picture</Text>
            </View>

            <View>

            <View>
            <TouchableOpacity onPress={()=>{ setVisible(false) }} >
            <FontAwesome name={"trash"} size={25} color= 
    {"#fff"} />
            </TouchableOpacity>
            <Text>Cancel</Text>
            </View>

            <View>
            <TouchableOpacity onPress={choosePhotoFromLibrary} >
            <FontAwesome name={"photo"} size={25}  color={"#fff"}/>
            </TouchableOpacity>
            <Text>Gallery</Text>
            </View>

            <View>
            <TouchableOpacity onPress= 
             {takePhotoFromCamera}> 
            <FontAwesome name={"camera"} size={25} color= 
           {"#fff"}/>
            </TouchableOpacity>
            <Text>Camera</Text>
            </View>

            </View>
            </View>

    );


}
Enter fullscreen mode Exit fullscreen mode

Note: Do not forget to install fontawesome package because we use it as well in the example above.
You can use any server technology like laravel to handle the backend.
Laravel code snippet to handle the uploading of the image

  if($request->filled('id') && 
     $request>filled('phone_number') && 
     $request->filled('extension') && 
     $request->has('image')) {
    $file = $request->file('image');
    $user_id = $request->input('id');
    $phone_number = $request->input('phone_number');
    $file_extension = $request->input('extension');

    $doesUserExist = User::where('id', $customer_id)
         ->where('phone_number', $phone_number)->exists();
    if($doesUserExist){
       $user = User::findOrFail($user_id);
       if(!empty($user->image)){
           Storage::disk('public')->delete($user->image);
        }
       $fileName = $user_id.''.time().'.'.$file_extension;
       $filePath = 
               $file->storeAs('images',$fileName,'public');
       $input = ['image' => $filePath];

       if($user->update($input)){
          $message = 'Profile updated successfully';
          $resp->statusCode = '1';
          $resp->message  = $message;
        }else {
          $resp->statusCode = '0';
          $resp->message = "Unable to update profile picture";
       }
 }else{
   $resp->statusCode = '0';
   $resp->message = "Unable to find user";
 }
}
 else{
  $resp->statusCode = '0';
  $resp->message = "Unable to process request";
 }
Enter fullscreen mode Exit fullscreen mode

I hope this post gives you a picture of how to upload profile picture or any photo from react native app to the server say laravel. Thank you for taking time to read through this post.

Top comments (0)