Loading Photos from the Filesystem
We’ve implemented photo taking and saving to the filesystem. There’s one last piece of functionality missing: the photos are stored in the filesystem, but we need a way to save pointers to each file so that they can be displayed again in the photo gallery.
Fortunately, this is easy: we’ll leverage the Capacitor Storage API to store our array of Photos in a key-value store.
Storage API
Begin by defining a constant variable that will act as the key for the store:
export class PhotoService {
public photos: Photo[] = [];
private PHOTO_STORAGE: string = "photos";
// other code
} Next, at the end of the
addNewToGallery function, add a call to
Storage.set() to save the Photos array. By adding it here, the Photos array is stored each time a new photo is taken. This way, it doesn’t matter when the app user closes or switches to a different app - all photo data is saved.
Storage.set({
key: this.PHOTO_STORAGE,
value: JSON.stringify(this.photos.map(p => {
// Don't save the base64 representation of the photo data,
// since it's already saved on the Filesystem
const photoCopy = { ...p };
delete photoCopy.base64;
return photoCopy;
}))
});
With the photo array data saved, create a function called loadSaved() that can retrieve that data. We use the same key to retrieve the photos array in JSON format, then parse it into an array:
public async loadSaved() {
// Retrieve cached photo array data
const photos = await Storage.get({ key: this.PHOTO_STORAGE });
this.photos = JSON.parse(photos.value) || [];
// more to come...
}
On mobile (coming up next!), we can directly set the source of an image tag -
<img src=”x” /> - to each photo file on the Filesystem, displaying them automatically. On the web, however, we must read each image from the Filesystem into base64 format, using a new
base64 property on the Photo object. This is because the Filesystem API uses
IndexedDB under the hood. Below the code you just added in the
loadSaved() function, add:
// Display the photo by reading into base64 format
for (let photo of this.photos) {
// Read each saved photo's data from the Filesystem
const readFile = await Filesystem.readFile({
path: photo.filepath,
directory: FilesystemDirectory.Data
});
// Web platform only: Save the photo into the base64 field
photo.base64 = `data:image/jpeg;base64,${readFile.data}`;
}
After, call this new method in tab2.page.ts so that when the user first navigates to Tab 2 (the Photo Gallery), all photos are loaded and displayed on the screen.
ngOnInit() {
this.photoService.loadSaved();
}
That’s it! We’ve built a complete Photo Gallery feature in our Ionic app that works on the web. Next up, we’ll transform it into a mobile app for iOS and Android!