In a react-native app (v61.5) using react-native-firebase (v5), I have an image path that goes something like this:
/message-attachments/{session-id}
i have scheduled message deletion after a certain period of time, during which any deleted message sessions which also have attachments stored at this session-id reference also gets deleted.
the problem is if a session gets archived, the image needs to be moved/duplicated from that message-attachments ref to lets say /{user}/archived-attachments/{session-id}
so it persists the scheduled message deletion.
firebase storage is used for this project, and im trying to achieve this from a duplication stand point so the reference path doesnt need to be entirely re-architected. according to the v5 react-native-firebase docs, putFile()
can ONLY take a device file path. but since the source of the image is another location in firebase, it seems that wont work. the only thing i can think of which might fit these requirements is to use .downloadFile('${firebase.storage.Native.DOCUMENT_DIRECTORY_PATH}/ok.jpeg')
and the in the same redux action use putFile('${firebase.storage.Native.DOCUMENT_DIRECTORY_PATH}/ok.jpeg')
to get it to the correct reference path in Storage.
this seems hacky and id prefer to avoid download the image to the users device, is there another way?
It is not good to download and re-upload a file. Theoretically, files may scale big and downloading files several megabytes large and then re-uploading them again is a bad solution.
Instead, you can create a cloud function that will do the move (copy/delete) operation.
const { Storage } = require('@google-cloud/storage');
exports.moveFile = functions.region(region).https.onCall(async (data, context) => {
// Simple mechanism to secure the function call to logged in users.
// There are other methods to secure cloud functions using IAM and
// you should always specify rules to the storage buckets to allow users
// view manage just their own files.
const { auth } = context || {};
const { uid } = auth || {};
if (!uid) {
throw 'Unauthenticated';
}
const srcBucketName = 'src-bucket';
const destBucketName = 'dest-bucket'; // Can be the same as source bucket
// Retrieve the file that the RN app passed to archive.
// We should also check if it's a valid file.
const { archiveFile } = data;
const srcFilename = `path/to/currentFile/${archiveFile}`;
const destFilename = `${uid}/archived-attachments/{session-id}/${srcFilename}`;
const storage = new Storage();
storage
.bucket(srcBucketName)
.file(srcFilename)
.copy(storage.bucket(destBucketName).file(destFilename))
.then(() => {
console.log(
`gs://${srcBucketName}/${srcFilename} copied to gs://${destBucketName}/${destFilename}.`
);
storage
.bucket(srcBucketName)
.delete()
.then(() => {
// Done moving file
return res.status(200);
})
.catch(err => {
console.error('DELETE ERROR:', err);
});
})
.catch(err => {
console.error('COPY ERROR:', err);
});
});
@react-native-firebase/functions
import firebase from '@react-native-firebase/app';
import '@react-native-firebase/functions';
firebase.app().functions(region).httpsCallable('moveFile')({
archiveFile: 'some-file.txt'
}).then(() => {
// Done moving file
}).catch(error => {
// Handle error
});