React Native: Take and choose images and uploaded it to Node.js

Let’s take a look at how to select and upload images from the gallery, or directly in the app

Louis Petrik
Teaching Tech
4 min readApr 29, 2020

--

Node.js React Native Images to Server
Node.js & React Native — a great combination!

In this tutorial we will show you how to use React Native & Expo to take an image from the native camera and send it directly to our server where we can save or edit it. We do this using Expo for React Native, and that’s it, no third party packages or native bridges — just the official modules of Expo.

As a backend we simply use Node.js with Express, where we receive the image converted to base64 via a Post Request and save it directly to our server as an image file using the FileSystem Module (fs). Here we go:

The complete source code for easy copy and paste can be found at the end, but until then I will explain the most important parts.

Create a new Expo project:
expo init <your-app-name>

Install the dependencies for the app:

expo install expo-image-picker expo-permissions

Install the dependencies for our backend:

npm install express body-parser

In our React Native App itself we will only work in our App.js which is created by default, that’s all we need.
The backend will also suffice as a single file somewhere, create it where you have installed express and body parser.

The imports of our App.js:

import React from ‘react’
import { StyleSheet, Text, View, Image, Button, Alert } from ‘react-native’
import * as ImagePicker from ‘expo-image-picker’
import * as Permissions from ‘expo-permissions’

Nothing special, expo itself provides us with the ImagePicker. Additionally we have to request the permissions to access the system’s gallery and the camera.

For this purpose, we create the askForPermission function, which asks via Expo whether the user would like to grant the app permission to access the system camera. Normally, this question is only asked once, when the app is first run. If it turns out afterwards that for whatever reason, the permission is not granted, we issue an alert.

const askForPermission = async () => {
const permissionResult =
await Permissions.askAsync(Permissions.CAMERA)
if (permissionResult.status !== ‘granted’) {
Alert.alert(‘no permissions to access camera!’,
[{ text: ‘ok’}])
return false
}
return true
}

Next we create our function with which we take and send our picture.
But the most interesting part is the ImagePicker.launchCameraAsync function with which we call the system camera. At the same time we pass some settings to it, which I explain below.

let image = await ImagePicker.launchCameraAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [3, 3],
quality: 1,
base64: true,
})

Via the mediaTypes we specify the file format that our app should select. In our case this means images.

allowsEditing simply specifies that the image can be cropped after capturing before it is sent.

aspect speaks for itself, with the quality we define the quality of the image, we can set it from 0–1, where 0 is bad and 1 is the best quality. The lower the quality, the smaller the base64 string and the final file.

base64 means that we want to keep the image in base64 format. This way our image is converted into a string which we can then simply send via HTTP requests like any other string.

After we made sure that a picture was really taken in our app, we can now send it to our server via post-request.

fetch(‘http://192.168.2.111:8080/', {
method: ‘POST’,
headers: {
Accept: ‘application/json’,
‘Content-Type’: ‘application/json’,
},
body: JSON.stringify({
imgsource: image.base64,
}),
})

We simply send the base64 attribute of our image object via the body of our post request, which gives us the base64-string.

Very important: If you use a real smartphone to run the app, you have to enter the network internal address for your server, not just the localhost as so often.

Our Backend

Here are the imports for our Node.js backend app:

const express = require(‘express’)
const bodyParser = require(‘body-parser’)
const app = express()
const fs = require(‘fs’)

With fs we can convert the received base64 string back into a real image file, bodyParser allows easy processing of post requests.

app.use(bodyParser.urlencoded({ extended: true }))
app.use(bodyParser.json({ limit: ‘15MB’ }))

We can (and should) set a maximum size for the incoming post-request. 15mb should be more than enough.

app.post(‘/’, (req, res) => {
fs.writeFile(‘./out.png’, req.body.imgsource, ‘base64’, (err) => {
if (err) throw err
})
res.status(200)
})

If a post request comes in under the “/” route of our serves, we convert the base64 code back into an image file and save it as out.png.
That’s it.

The full code

App.js:

server.js:

Thank you for reading :)

Unlock unlimited access to quality content with a Medium membership while supporting me!*

*Affiliate links. If you use these links to purchase something, I will earn a commission, but there is no additional cost for you. Thank you very much!

If you’d like to learn more about what cool things you can do with the FileSystem in Node.js, check this out:

--

--