In this tutorial, you will learn how to capture or pick an image in an Ionic 8 app, convert it to base64 (if needed), and upload it to a backend server using Angular 20’s standalone components and Capacitor 5. This replaces the older Cordova plugin method with the latest Capacitor APIs.
Prerequisites
Make sure you have:
-
Node.js v20+
-
Ionic CLI v7+
-
Basic understanding of Ionic and Angular
-
A running backend API that accepts file uploads (e.g., Express, Laravel, Django)
Step 1 – Create a New Ionic Angular Standalone App
npm install -g @ionic/cli
ionic start imageUploadApp blank --type=angular
cd imageUploadApp
Enable Capacitor integration:
ionic integrations enable capacitor
For the tutorial sanitation, run the app on the browser, then type this command.
ionic serve
That command will open the default browser with inspect mode and display this page.
Step 2 – Install Capacitor Camera & HTTP Dependencies
npm install @capacitor/camera
npm install @angular/common @angular/forms @angular/platform-browser @angular/platform-browser-dynamic @angular/router
ionic build
npx cap sync
Step 3 – Bootstrap Without NgModule
Open src/main.ts
and replace with:
import { bootstrapApplication } from '@angular/platform-browser';
import { RouteReuseStrategy, provideRouter, withPreloading, PreloadAllModules } from '@angular/router';
import { IonicRouteStrategy, provideIonicAngular } from '@ionic/angular/standalone';
import { routes } from './app/app.routes';
import { AppComponent } from './app/app.component';
import { provideHttpClient } from '@angular/common/http';
bootstrapApplication(AppComponent, {
providers: [
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
provideIonicAngular(),
provideRouter(routes, withPreloading(PreloadAllModules)),
provideHttpClient(),
],
});
Step 4 – Create the App Component
Replace src/app/home/home.page.ts
with:
import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';
import { IonHeader, IonToolbar, IonTitle, IonContent, IonButton } from '@ionic/angular/standalone';
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
imports: [CommonModule, IonButton, IonHeader, IonToolbar, IonTitle, IonContent],
})
export class HomePage {
photoDataUrl: string | null = null;
constructor(private http: HttpClient) { }
async takePhoto() {
const image = await Camera.getPhoto({
quality: 80,
resultType: CameraResultType.DataUrl,
source: CameraSource.Camera
});
this.photoDataUrl = image.dataUrl!;
}
async pickImage() {
const image = await Camera.getPhoto({
quality: 80,
resultType: CameraResultType.DataUrl,
source: CameraSource.Photos
});
this.photoDataUrl = image.dataUrl!;
}
upload() {
if (!this.photoDataUrl) return;
const blob = this.dataUrlToBlob(this.photoDataUrl);
const formData = new FormData();
formData.append('file', blob, 'photo.jpg');
this.http.post('https://your-server.com/upload', formData)
.subscribe({
next: res => console.log('Upload success', res),
error: err => console.error('Upload failed', err)
});
}
private dataUrlToBlob(dataUrl: string): Blob {
const arr = dataUrl.split(',');
const mime = arr[0].match(/:(.*?);/)![1];
const bstr = atob(arr[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
}
}
Replace src/app/home/home.page.html
with:
<ion-header>
<ion-toolbar>
<ion-title>Image Upload</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-button expand="block" (click)="takePhoto()">Take Photo</ion-button>
<ion-button expand="block" (click)="pickImage()"
>Pick from Gallery</ion-button
>
@if (photoDataUrl) {
<div class="preview">
<img [src]="photoDataUrl" alt="Preview" />
<ion-button color="success" expand="block" (click)="upload()"
>Upload</ion-button
>
</div>
}
</ion-content>
Step 5 – Update Android/iOS Permissions
Android
Add Android platform:
npm install @capacitor/android
npx cap add android
Open android/app/src/main/AndroidManifest.xml
and ensure:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
iOS
Add iOS platform:
npm install @capacitor/ios
npx cap add ios
n ios/App/App/Info.plist
:
<key>NSCameraUsageDescription</key>
<string>We need access to your camera to take photos.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to your photo library to choose images.</string>
Step 6 – Build and Run
ionic build
npx cap open android
npx cap open ios
Run on a real device to test the camera and upload.
Step 7 – Backend Upload Script Example (Node.js Express)
import express from 'express';
import multer from 'multer';
import cors from 'cors';
const app = express();
app.use(cors());
const upload = multer({ dest: 'uploads/' });
app.post('/upload', upload.single('file'), (req, res) => {
console.log(req.file);
res.json({ message: 'File uploaded successfully' });
});
app.listen(3000, () => console.log('Server running on port 3000'));
Conclusion
You’ve now modernized the old Ionic 3 + Angular 5 + Cordova base64 upload flow to Ionic 8 + Angular 20 standalone + Capacitor 5.
This approach:
-
Works on Android, iOS, and Web
-
Uses Capacitor APIs instead of deprecated Cordova plugins
-
Keeps the code clean and standalone-friendly
Don't worry, you can compare the tutorial to the working source code on our GitHub.
We know that building beautifully designed Ionic apps from scratch can be frustrating and very time-consuming. Check Ionic 6 - Full Starter App and save development and design time. Android, iOS, and PWA, 100+ Screens and Components, the most complete and advanced Ionic Template.
That's just the basics. If you need more deep learning about Ionic, Angular, and TypeScript, you can take the following cheap course:
- Ionic Apps with Firebase
- Ionic Apps for WooCommerce: Build an eCommerce Mobile App
- Ionic 8+: Build Food Delivery App from Beginner to Advanced
- IONIC - Build Android & Web Apps with Ionic
- Full Stack Development with Go, Vuejs, Ionic & MongoDB
- Create a Full Ionic App with Material Design - Full Stack
Thanks!