Hi
I’ve created an application that takes photos and then needs to send them up to a server.
The problem that I’m having is that when doing the upload only some of the images are sent to the server.
It seems that images that come from the file location work fine.
file:///data/user/0/io.ionic.starter/files/filename.jpg
and then the images that come from the cache don’t upload at all.
file:///data/user/0/io.ionic.starter/cache/filename.jpeg
First question, what would cause the same code to save the images in different locations? Could this be a product of using local storage?
I’ve pretty much followed the Your First Ionic App: React tutorial to create the app. I did make some changes as I didn’t require a gallery.
I’ve included the entire hook file that I’m using below.
Thanks in advance.
import { useState, useEffect } from "react";
import { useCamera } from "@ionic/react-hooks/camera";
import { useFilesystem, base64FromPath } from "@ionic/react-hooks/filesystem";
import { useStorage } from "@ionic/react-hooks/storage";
import { isPlatform } from "@ionic/react";
import {
CameraResultType,
CameraSource,
CameraPhoto,
Capacitor,
FilesystemDirectory,
} from "@capacitor/core";
export interface Photo {
filepath: string;
webviewPath?: string;
base64?: string;
}
export interface GalleryPhoto {
webviewPath?: string;
base64?: string;
}
const PHOTO_STORAGE = "photos";
export function usePhoto() {
const { getPhoto } = useCamera();
const [photos, setPhotos] = useState<Photo[]>([]);
const { deleteFile, getUri, readFile, writeFile } = useFilesystem();
const { get } = useStorage();
useEffect(() => {
/* On mobile, we can directly point to each photo file on the Filesystem and
display 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. */
const loadSaved = async () => {
const photosString = await get(PHOTO_STORAGE);
const photosInStorage = (photosString
? JSON.parse(photosString)
: []) as Photo[];
// Running on the web
if (!isPlatform("hybrid")) {
for (let photo of photosInStorage) {
const file = await readFile({
path: photo.filepath,
directory: FilesystemDirectory.Data,
});
photo.base64 = `data:image/jpeg;base64,${file.data}`;
}
}
setPhotos(photosInStorage);
};
loadSaved();
}, [get, readFile]);
const takePhoto = async (fileNamePrefix: string) => {
const cameraPhoto = await getPhoto({
resultType: CameraResultType.Uri,
source: CameraSource.Camera,
quality: 65,
width: 700,
height: 900,
});
const fileName = `${fileNamePrefix}-${new Date().getTime()}.jpg`;
// return await savePhoto(cameraPhoto, fileName);
const savedFileImage = await savePhoto(cameraPhoto, fileName);
// console.log(savedFileImage.base64);
// console.log(savedFileImage.filepath);
// console.log(savedFileImage.webviewPath);
const newPhotos: Photo[] = [savedFileImage, ...photos];
setPhotos(newPhotos);
};
const savePhoto = async (photo: CameraPhoto, fileName: string) => {
let base64Data: string;
// Check if we are running on Capacitor or Cordova. (On mobile device)
if (isPlatform("hybrid")) {
const file = await readFile({
path: photo.path!,
});
base64Data = file.data;
} else {
base64Data = await base64FromPath(photo.webPath!);
}
await writeFile({
path: fileName,
data: base64Data,
directory: FilesystemDirectory.Data,
});
return getPhotoFile(photo, fileName, base64Data);
};
const getPhotoFile = async (
cameraPhoto: CameraPhoto,
fileName: string,
base64: string
): Promise<Photo> => {
if (isPlatform("hybrid")) {
// Get the new, complete filepath of the photo saved on filesystem
const fileUri = await getUri({
directory: FilesystemDirectory.Data,
path: fileName,
});
// Display the new image by rewriting the 'file://' path to HTTP
// Details: https://ionicframework.com/docs/building/webview#file-protocol
return {
filepath: fileUri.uri,
webviewPath: Capacitor.convertFileSrc(fileUri.uri),
base64,
};
}
// Use webPath to display the new image instead of base64 since it's already loaded into memory
return {
filepath: fileName,
webviewPath: cameraPhoto.webPath,
base64,
};
};
const deletePhoto = async (photo: Photo) => {
// Remove this photo from the Photos reference data array
const newPhotos = photos.filter((p) => p.filepath !== photo.filepath);
// delete photo from filesystem
const filename = photo.filepath.substr(photo.filepath.lastIndexOf("/") + 1);
await deleteFile({
path: filename,
directory: FilesystemDirectory.Data,
});
setPhotos(newPhotos);
};
const selectPhoto = async (): Promise<void> => {
const galleryPhoto = await getPhoto({
resultType: CameraResultType.Uri,
source: CameraSource.Photos,
quality: 100,
});
const photo = {
filepath: galleryPhoto.path ?? "",
webviewPath: galleryPhoto.webPath,
base64: galleryPhoto.base64String,
};
const newPhotos: Photo[] = [photo, ...photos];
setPhotos(newPhotos);
};
return { photos, takePhoto, selectPhoto, deletePhoto };
}