Uploading images to a server is a very common task in most mobile apps. This task can be challenging for some developers. This article will show you step by step how to upload images on your React Native app to a Laravel API.
This article has two parts.
- Laravel API
- React Native App
PART 1: Laravel API
Step 1: Create a new Laravel project using composer. You can give it any name but in this case, we will name it ImageApi.
composer create-project --prefer-dist laravel/laravel ImageApi
Step 2: In the ImageApi project create a migration to create an images table.
php artisan make:migration create_images_table --create=images
Step 3: In the migration add the image fields Title and Uri.
<?phpuse Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration;class CreateImagesTable extends Migration {
public function up()
{
Schema::create(‘images’, function (Blueprint $table) {
$table->increments(‘id’);
$table->string(‘title’);
$table->string(‘uri’);
$table->timestamps();
});
}
public function down()
{
Schema::drop('images');
}
}
Step 4: Next, create a model called Image
php artisan make:model Image
Step 5: In the model add the image fields and Uri fields in the fillable array.
<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class Image extends Model { protected $table = 'images'; protected $fillable = [ 'title', 'url' ]; }
Step 5: Next, create a controller and name it ImageController.
php artisan make:controller ImageController
Step 6: To the Image controller, add a function called addimage.
<?phpnamespace App\Http\Controllers;use App\Image; use App\Http\Controllers\Controller;class ImageController extends Controller {
public function addimage(Request $request)
{
$image = new Image; $image->title = $request->title;
if ($request->hasFile(‘image’)) {
$path = $request->file(‘image’)->store(‘images’);
$image->url = $path; } $image->save(); return new ImageResource($image); } }
Step 7: Finally in the api.php file in the routes folder
<?phpuse Illuminate\Http\Request;
Route::resource(‘imageadd’, ‘Api\ImageController@addimage’);
This will create an Api endpoint
<domain>/api/imageadd
The React Native App will access this API endpoint.
PART 2: React Native App
Step 1: Create a new React Native project using expo. Call it imageUploaderApp.
expo init imageUploaderApp
Step 2: Then install formik library to the app. Read Formik Documentation here.
npm install formik --save
Step 3: Install Expo image Picker to the app. Read Expo Image Picker documentation here.
expo install expo-image-picker
Step 4: Next, install RN Blob Fetch to the app. Read RN Blob Fetch documentation here.
npm install --save rn-fetch-blob
On the App.js of your React Native App
Step 5: Create two state variables using useState. The first variable will store the image file and the second variable will store the image URI.
const [fileContent, setFileContent] = useState(null);
const [fileUri, setFileUri] = useState(null);
Step 6: Create a handler function to choose an image from the system image library.
onChooseImagePress = async () => {
let result = await ImagePicker.launchImageLibraryAsync();
if (!result.cancelled){
setFileContent(result.uri);
setFileUri(result.uri.toString());
}
}
Step 7: Then create a formik constant using the useFormik state hook
const formik = useFormik({
initialValues: { title: '' },
onSubmit: values => {
RNFetchBlob.fetch('POST', `<domain-name>/api/imageadd`, {
‘Content-Type’ : ‘multipart/form-data’,
},
[
{
name : ‘image’,
filename : fileUri,
type:’image/jpeg’,
data: RNFetchBlob.wrap(fileContent)
},
{
name : ‘title’,
data : values.title
},
]).then((resp) => {
// …
}).catch((err) => {
Alert.alert(‘An error occurred!’, err.message, [{ text: ‘Okay’ }]);
})
}
});
The final app.js file should look like this:
import React, { useState, useEffect } from 'react';
import { StyleSheet, View, Text, Image, Alert} from ‘react-native’;
import { useFormik } from ‘formik’;
import * as ImagePicker from ‘expo-image-picker’;
import RNFetchBlob from ‘rn-fetch-blob’;const App = () => {const [fileContent, setFileContent] = useState(null);
const [fileUri, setFileUri] = useState(”);
onChooseImagePress = async () => {
let result = await ImagePicker.launchImageLibraryAsync();
if (!result.cancelled){
setFileContent(result.uri);
setFileUri(result.uri.toString());
}
}const formik = useFormik({
initialValues: { title: ” },
onSubmit: values => {
RNFetchBlob.fetch(‘POST’, `<domain-name>/api/imageadd`,{
‘Content-Type’ : ‘multipart/form-data’,
},
[
{
name : ‘image’,
filename : fileUri,
type:’image/jpeg’,
data: RNFetchBlob.wrap(fileContent)
},
{
name : ‘title’,
data : values.title
},
]).then((resp) => {
// …
}).catch((err) => {
Alert.alert(‘An error occurred!’, err.message, [{ text: ‘Okay’ }]);
})
}
});return(
<View>
<Text>{fileUri}</Text>
<TextInput
onChangeText={formik.handleChange(‘title’)}
value={formik.values.title}
label=’Title’
placeholder=’e.g My Awesome Selfie’
/>
<Button onPress={() => {onChooseImagePress()}} >Choose image…</Button>
<Button title=’submit’ onPress={formik.handleSubmit} >Enter Picture</Button>
</View>
)
}export default App;