i have tried to encrypt the folder using aes-256-cbc in nodejs. Encryption works fine but decryption of files shows is error
Error: error:1C800064:Provider routines::bad decrypt at Decipheriv.final (node:internal/crypto/cipher:193:29) at /Users/vikasrushi/ipfs-encryption/utils.js:56:33 at FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read_file_context:68:3) { library: 'Provider routines', reason: 'bad decrypt', code: 'ERR_OSSL_BAD_DECRYPT' }
These code i have used to encrypt the files and decryption function throws error. instead of random iv i took constant and for password too. am i missing something
const fs = require("fs");
const algorithm = "aes-256-cbc";
const password = Buffer.from(
"bf3c199c2470cb477d907b1e0917c17bbf3c199c2470cb477d907b1e0917c17b",
"hex"
); // set random encryption key
const iv = Buffer.from("5183666c72eec9e45183666c72eec9e4", "hex"); // set random initialisation vectors
const encryptFolder = (folderPath) => {
// const hash = crypto.createHash("sha256").update(password).digest();
fs.readdir(folderPath, (err, files) => {
if (err) throw err;
// Encrypt each file in the folder
for (const file of files) {
fs.readFile(`${folderPath}/${file}`, (err, data) => {
if (err) throw err;
// Encrypt the data
console.log(iv);
const cipher = crypto.createCipheriv(algorithm, password, iv);
let encrypted = cipher.update(data, "utf8", "hex");
encrypted += cipher.final("hex");
// Write the encrypted data to a new file
fs.writeFile(`./encrypted/${file}.encrypted`, encrypted, (err) => {
if (err) throw err;
});
});
}
});
};
const decryptFolder = (encryptedFolderPath) => {
// const hash = crypto.createHash("sha256").update(password).digest();
// const iv = crypto.randomBytes(16); // not working
// Read the encrypted folder contents
fs.readdir(encryptedFolderPath, (err, encryptedFiles) => {
if (err) throw err;
// Decrypt each file in the folder
for (const encryptedFile of encryptedFiles) {
fs.readFile(
`${encryptedFolderPath}/${encryptedFile}`,
(err, encryptedData) => {
if (err) throw err;
// Decrypt the data
const decipher = crypto.createDecipheriv(algorithm, password, iv);
let decrypted = decipher.update(encryptedData, "hex", "utf8");
decrypted += decipher.final("utf8");
fs.writeFile(
`./decrypted/${encryptedFile.replace(".encrypted", "")}`,
decrypted,
(err) => {
if (err) throw err;
}
);
}
);
}
});
};
module.exports = { encryptFolder, decryptFolder };
Related
i have a problem, when i upload an image to Cloud Storage it returns me this error:
{
"error": {
"code": 400,
"message": "Invalid HTTP method/URL pair."
}
}
im using expo with image pick to get the image from my device
const elegirImagen =async () => {
let res = await imagePicker.launchImageLibraryAsync({
mediaTypes: imagePicker.MediaTypeOptions.Images,
allowsEditing:true,
aspect:[4,3],
quality:1,
});
if(!res.cancelled){
const source = {uri:res.uri}
console.log('imgage picker if',source)
setImagen(source)
}
}
this saves the image
const uploadImage = async()=>{
if(!imagen) return
const metadata = {
contentType: 'image/jpeg',
};
console.log('imagen uri upload', imagen.uri)
const res = await fetch(imagen.uri);
const blob = await res.blob();
const filename = imagen.uri.substring(imagen.uri.lastIndexOf('/')+1)
// Upload file and metadata to the object 'images/mountains.jpg'
const storageRef = ref(storage, `./images/${filename}` + filename);
const uploadTask = uploadBytesResumable(storageRef, blob, metadata);
// Listen for state changes, errors, and completion of the upload.
uploadTask.on('state_changed',
(snapshot) => {
// Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
setProgreso(progress)
switch (snapshot.state) {
case 'paused':
console.log('Upload is paused');
break;
case 'running':
console.log('Upload is running');
break;
}
},
(error) => {
// A full list of error codes is available at
// https://firebase.google.com/docs/storage/web/handle-errors
switch (error.code) {
case 'storage/unauthorized':
// User doesn't have permission to access the object
break;
case 'storage/canceled':
// User canceled the upload
break;
// ...
case 'storage/unknown':
// Unknown error occurred, inspect error.serverResponse
break;
}
},
() => {
// Upload completed successfully, now we can get the download URL
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
console.log('File available at', downloadURL);
});
}
)}
and this uploads the image as firebase docs says but when i check de database i always get this
Finally solved it. the solution was to change the path in the database storage
const storageRef = ref(storage, `images/` + filename);
I have the following Function that:
Listens for document (text message) creation
Grab IDs of members of a group chat
Get the FCM Tokens for each member
With a for-loop, send messages to group members
exports.sendChatMessage = functions.firestore
.document("chats/{mealID}/messages/{messageID}")
.onCreate((snap, context) => {
const data = snap.data();
const mealID = context.params.mealID;
const senderID = data.senderID;
const senderName = data.senderName;
const messageContent = data.content;
var docRef = db.collection("chats").doc(mealID);
docRef
.get()
.then((doc) => {
if (doc.exists) {
const docData = doc.data();
const mealName = docData.name;
const userStatus = docData.userStatus;
var users = docData.to;
var eligibleUsers = users.filter(
(user) => userStatus[user] == "accepted"
);
eligibleUsers.push(docData.from);
// get fcmTokens from eligibleUsers and send the messagme
db.collection("users")
.where("uid", "in", eligibleUsers)
.get()
.then((snapshot) => {
var fcmTokens = [];
var thumbnailPicURL = "";
// get thumbnailpic of the sender and collect fcmTokens
snapshot.forEach((doc) => {
if (doc.data().uid == senderID) {
thumbnailPicURL =
doc.data().thumbnailPicURL == null
? "https://i.imgur.com/8wSudUk.png"
: doc.data().thumbnailPicURL;
} else {
fcmTokens.push(doc.data().fcmToken);
}
});
// send the message fcmTokens
fcmTokens.forEach((token) => {
if (token != "") {
const fcmMessage = {
message: {
token: token,
notification: {
title: mealName,
body: senderName + ": " + messageContent,
image: thumbnailPicURL,
},
apns: {
payload: {
aps: {
category: "MESSAGE_RECEIVED",
},
MEAL_ID: mealID,
},
},
},
};
tokenManger.sendFcmMessage(fcmMessage);
}
});
return true;
});
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
return false;
}
})
.catch((error) => {
console.log("Error getting document:", error);
return false;
});
return true;
});
My send function comes from a helper file that uses the HTTP V1 protocol to build the send-request:
const { google } = require("googleapis");
const https = require("https");
const MESSAGING_SCOPE = "https://www.googleapis.com/auth/firebase.messaging";
const SCOPES = [MESSAGING_SCOPE];
const PROJECT_ID = MY_PROJECT_ID;
const HOST = "fcm.googleapis.com";
const PATH = "/v1/projects/" + PROJECT_ID + "/messages:send";
exports.getAccessToken = () => {
return new Promise(function (resolve, reject) {
const key = require("./service-account.json");
var jwtClient = new google.auth.JWT(
key.client_email,
null,
key.private_key,
SCOPES,
null
);
jwtClient.authorize(function (err, tokens) {
if (err) {
reject(err);
return;
}
resolve(tokens.access_token);
});
});
};
//send message
exports.sendFcmMessage = (fcmMessage) => {
this.getAccessToken().then(function (accessToken) {
var options = {
hostname: HOST,
path: PATH,
method: "POST",
headers: {
Authorization: "Bearer " + accessToken,
},
// … plus the body of your notification or data message
};
var request = https.request(options, function (resp) {
resp.setEncoding("utf8");
resp.on("data", function (data) {
console.log("Message sent to Firebase for delivery, response:");
console.log(data);
});
});
request.on("error", function (err) {
console.log("Unable to send message to Firebase");
console.log(err);
});
request.write(JSON.stringify(fcmMessage));
request.end();
});
};
It worked all fine in the emulator but once deployed, there're significant delays (~3 mins):
I also noticed that the console says the cloud function finishes execution BEFORE sendFcmMessage logs success messages.
I did some research online, it appears that it might have something to do with the usage of Promise but I wasn't sure if that's the sole reason or it has something to do with my for-loop.
The Problem
To summarize the issue, you are creating "floating promises" or starting other asynchronous tasks (like in sendFcmMessage) where you aren't returning a promise because they use callbacks instead.
In a deployed function, as soon as the function returns its result or the Promise chain resolves, all further actions should be treated as if they will never be executed as documented here. An "inactive" function might be terminated at any time, is severely throttled and any network calls you make (like setting data in database or calling out to FCM) may never be executed.
An indicator that you haven't properly chained the promises is when you see the function completion log message ("Function execution took...") before other messages you are logging. When you see this, you need to look at the code you are running and confirm whether you have any "floating promises" or are using callback-based APIs. Once you have changed the callback-based APIs to use promises and then made sure they are all chained together properly, you should see a significant boost in performance.
The fixes
Sending the message data to FCM
In your tokenManger file, getAccessToken() could be reworked slightly and sendFcmMessage should be converted to return a Promise:
exports.getAccessToken = () => {
return new Promise(function (resolve, reject) {
const key = require("./service-account.json");
const jwtClient = new google.auth.JWT(
key.client_email,
null,
key.private_key,
SCOPES,
null
);
jwtClient.authorize(
(err, tokens) => err ? reject(err) : resolve(tokens.access_token)
);
});
};
//send message
exports.sendFcmMessage = (fcmMessage) => {
// CHANGED: return the Promise
return this.getAccessToken().then(function (accessToken) {
const options = {
hostname: HOST,
path: PATH,
method: "POST",
headers: {
Authorization: "Bearer " + accessToken,
},
// … plus the body of your notification or data message
};
// CHANGED: convert to Promise:
return new Promise((resolve, reject) => {
const request = https.request(options, (resp) => {
resp.setEncoding("utf8");
resp.on("data", resolve);
resp.on("error", reject);
});
request.on("error", reject);
request.write(JSON.stringify(fcmMessage));
request.end();
});
});
};
However, the above code was built for googleapis ^52.1.0 and google-auth-library ^6.0.3. The modern versions of these modules are v92.0.0 and v7.11.0 respectively. This means you should really update the code to use these later versions like so:
// Import JWT module directly
const { JWT } = require('google-auth-library');
// FIREBASE_CONFIG is a JSON string available in Cloud Functions
const PROJECT_ID = JSON.parse(process.env.FIREBASE_CONFIG).projectId;
const FCM_ENDPOINT = `https://fcm.googleapis.com/v1/projects/${PROJECT_ID}/messages:send`;
const FCM_SCOPES = ["https://www.googleapis.com/auth/firebase.messaging"];
exports.sendFcmMessage = (fcmMessage) => {
const key = require("./service-account.json"); // consider moving outside of function (so it throws an error during deployment if its missing)
const client = new JWT({
email: key.client_email,
key: key.private_key,
scopes: FCM_SCOPES
});
return client.request({ // <-- this uses `gaxios`, Google's fork of `axios` built for Promise-based APIs
url: FCM_ENDPOINT,
method: "POST",
data: fcmMessage
});
}
Better yet, just use the messaging APIs provided by the Firebase Admin SDKs that handle the details for you. Just feed it the message and tokens as needed.
import { initializeApp } from "firebase-admin/app";
import { getMessaging } from "firebase-admin/messaging";
initializeApp(); // initializes using default credentials provided by Cloud Functions
const fcm = getMessaging();
fcm.send(message) // send to one (uses the given token)
fcm.sendAll(messagesArr) // send to many at once (each message uses the given token)
fcm.sendMulticast(message) // send to many at once (uses a `tokens` array instead of `token`)
The Cloud Function
Updating the main Cloud Function, you'd get:
exports.sendChatMessage = functions.firestore
.document("chats/{mealID}/messages/{messageID}")
.onCreate((snap, context) => {
const mealID = context.params.mealID;
const { senderID, senderName, content: messageContent } = snap.data();
const docRef = db.collection("chats").doc(mealID);
/* --> */ return docRef
.get()
.then((doc) => {
if (!doc.exists) { // CHANGED: Fail fast and avoid else statements
console.log(`Could not find "chat:${mealID}"!`);
return false;
}
const { userStatus, to: users, name: mealName, from: fromUser } = doc.data();
const eligibleUsers = users.filter(
(user) => userStatus[user] == "accepted"
);
eligibleUsers.push(fromUser);
// get fcmTokens from eligibleUsers and send the message
/* --> */ return db.collection("users")
.where("uid", "in", eligibleUsers) // WARNING: This will only work for up to 10 users! You'll need to break it up into chunks of 10 if there are more.
.get()
.then(async (snapshot) => {
const fcmTokens = [];
let thumbnailPicURL = "";
// get thumbnailpic of the sender and collect fcmTokens
snapshot.forEach((doc) => {
if (doc.get("uid") == senderID) {
thumbnailPicURL = doc.get("thumbnailPicURL"); // update with given thumbnail pic
} else {
fcmTokens.push(doc.get("fcmToken"));
}
});
const baseMessage = {
notification: {
title: mealName,
body: senderName + ": " + messageContent,
image: thumbnailPicURL || "https://i.imgur.com/8wSudUk.png", // CHANGED: specified fallback image here
},
apns: {
payload: {
aps: {
category: "MESSAGE_RECEIVED",
},
MEAL_ID: mealID,
},
}
}
// log error if fcmTokens empty?
// ----- OPTION 1 -----
// send the message to each fcmToken
const messagePromises = fcmTokens.map((token) => {
if (!token) // handle "" and undefined
return; // skip
/* --> */ return tokenManger
.sendFcmMessage({
message: { ...baseMessage, token }
})
.catch((err) => { // catch the error here, so as many notifications are sent out as possible
console.error(`Failed to send message to "fcm:${token}"`, err);
})
});
await Promise.all(messagePromises); // wait for all messages to be sent out
// --------------------
// ----- OPTION 2 -----
// send the message to each fcmToken
await getMessaging().sendAll(
fcmTokens.map((token) => ({ ...baseMessage, token }))
);
// --------------------
return true;
})
.catch((error) => {
console.log("Error sending messages:", error);
return false;
});
})
.catch((error) => {
console.log("Error getting document:", error);
return false;
});
});
I found out that the culprit is my queries to db. Like #samthecodingman commented, I was creating floating Promises.
Originally, I have codes like:
db.collection("users")
.where("uid", "in", eligibleUsers)
.get()
.then((snapshot) => {...}
All I needed to do is to return that call:
return db.collection("users")
.where("uid", "in", eligibleUsers)
.get()
.then((snapshot) => {...}
Although it's still not instant delivery, it's much faster now.
So, I have my route which console.logs 'undefined':
router.get("/validate-pin", async (req, res) => {
// restrict when done
try {
const { userId, pin } = req.query;
const isActivePin = await pinsDB.compareActivePin(userId, pin);
console.log(isActivePin)
return res.status(200).json(isActivePin);
} catch (error) {
console.log(error);
res.status(500).json({ error: "db error: ", error });
}
});
I have my compareActivePin method, which logs out the 'res' parameter, but for some reason doesn't return it:
async function compareActivePin(userId, received_pin) {
const active_pin = await db("account_pins").where({ userId, isActive: true });
const pinIsValidated = bcrypt.compareSync(
received_pin,
active_pin[0].account_pin
);
if (pinIsValidated) {
let skLocation = await db("sks").where({ userId }).select("url");
await readKey(skLocation[0].url, (res) => {
// console.log(res);
return res;
});
} else return false;
}
And I have my readKey method, which actually grabs the data I want my compareActivePin to return. This works like a charm.
const readKey = async (key, callback) => {
const aws = require("aws-sdk");
aws.config.update({
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
region: "us-east-2",
});
const s3 = new aws.S3();
const getParams = { Bucket: process.env.SK_BUCKET, Key: `${key}.txt` };
await s3.getObject(getParams, (err, data) => {
if (err) return err;
return callback(data.Body.toString());
});
};
So, just to recap. When I hit my endpoint, I pass in a userId and pin (strings). This calls the compareActivePin method which validates the pin and then, if the pin is valid, it then calls readKey, which grabs the file from S3 and returns the text within the file.
Like I said, I'm able to log it out to the console from within the readKey callback, but when I try to log it out as the returned value from the route, it comes back undefined.
Hoping someone could point me in the right direction.
Thanks...
I ended up answering my own question. I don't think it's possible to get a return value from the callback, so I ended up paring down the call from the database and sending the response from the readKey function using the router response object, like so:
//CompareActivePin Function
async function compareActivePin(userId, received_pin) {
const active_pin = await db("account_pins").where({ userId, isActive: true });
const pinIsValidated = bcrypt.compareSync(
received_pin,
active_pin[0].account_pin
);
return pinIsValidated;
}
//Router Call
router.get("/validate-pin", async (req, res) => {
// restrict when done
try {
const { userId, pin } = req.query;
const isActivePin = await pinsDB.compareActivePin(userId, pin);
if (isActivePin) {
let skLocation = await skDB.findUrl(userId);
readKeyFunc(skLocation[0].url, (result) => {
return res.status(200).json({ confirmed: isActivePin, key: result });
});
} else return res.status(401).json({ confirmed: isActivePin, key: null });
} catch (error) {
res.status(500).json({ error: "db error: ", error });
}
});
This also goes a long way toward keeping my database methods pure and separating my concerns.
Thanks, StackOverflow!
here is my code:-
exports.uploadImage = (req, res) => {
const BusBoy = require('busboy');
const path = require('path');
const os = require('os');
const fs = require('fs');
const busboy = new BusBoy({ headers: req.headers });
let imageFileName;
let imageToBeUploaded = {};
busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
const imageExtension = filename.split('.')[filename.split('.').length - 1];
imageFileName = `${Math.round(Math.random() * 100000000000)}.${imageExtension}`;
const filepath = path.join(os.tmpdir(), imageFileName);
imageToBeUploaded = { filepath, mimetype };
file.pipe(fs.createWriteStream(filepath));
});
busboy.on('finish', () => {
console.log('Busboy on started');
//code breaks here
admin.storage().bucket().upload(imageToBeUploaded.filepath, {
resumable: false,
metadata: {
metadata: {
contentType: imageToBeUploaded.mimetype
}
}
})
.then(() => {
const imageUrl = `https://firebasestorage.googleapis.com/v0/b/${config.storageBucket}/o/${imageFileName}?alt=media`;
console.log('logging image url' + imageUrl);
return db.doc(`/users/${req.user.handle}`).update({ imageUrl })
})
.then(() => {
return res.json({ message: 'Image uploaded successfully' });
})
.catch(err => {
console.error(err);
return res.status(500).json({ error: err.code });
})
});
busboy.end(req.rawBody);
}
I have mentioned where my code is breaking in a comment and the error I am getting is Error: Cannot parse response as JSON: Not Found
message: 'Cannot parse response as JSON: Not Found'
The error message says cannot parse response as JSON. Does that mean the response from firebase is not JSON? I have a token in the header of the request and an image in the body as form-data. I really have not clue what wrong, please help
I unfortunately can't identify the JSON parsing error, so I've instead rewritten the code to be more streamlined as #robsiemb eluded to.
Your uploadImage function appears to be configured as some middleware, so I have done the same below. This code will stream the uploaded data straight to Cloud Storage under a unique file name as generated from Reference.push().key to prevent conflicts.
In the code below,
The uploaded file will be stored at a location similar to: userData/someUserId/images/-JhLeOlGIEjaIOFHR0xd.png
The image's raw URL is not stored in the database because unless the file object or containing bucket is made public it will require a signed URL which can only last up to 7 days (see below).
More than one file can be accepted and uploaded. If this is undesired, configure the limits for the BusBoy instance.
Basic error handling for non-POST requests and missing file entries was added.
// import Firebase libraries & initialize
const admin = require('firebase-admin');
admin.initializeApp(); // initializes from environment variables
// import required modules
const BusBoy = require('busboy');
exports.uploadImage = (req, res) => {
if (req.method !== 'POST') {
res.sendStatus(405); // 405 METHOD_NOT_ALLOWED
return;
}
let busboy = new BusBoy({headers: req.headers}); // add {limits: {files: 1}} to limit to only a single file upload
let bucket = admin.storage().bucket();
let db = admin.firestore();
let storageFilepath;
let storageFile;
// Note: Currently only the last file is saved to `/users/${req.user.handle}`
busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
let fileext = filename.match(/\.[0-9a-z]+$/i)[0];
storageFilepath = `userData/${req.user.handle}/images/` + getUniqueName() + fileext;
storageFile = bucket.file(storageFilepath);
file.pipe(storageFile.createWriteStream({ gzip: true }));
})
.on('finish', () => {
if (!storageFile) {
res.status(400).json({error: 'expected file'}); // 400 BAD_REQUEST
return;
}
db.doc(`/users/${req.user.handle}`).update({ imagePath: storageFilepath })
.then(() => {
res.status(201).json({ message: 'Image uploaded successfully' }); // 201 CREATED
})
.catch((err) => {
console.error(err);
res.status(500).json({ error: err.code }); // 500 INTERNAL_SERVER_ERROR
});
})
.on('error', (err) => {
console.error(err);
res.status(500).json({ error: err.code });
});
req.pipe(busboy);
});
function getUniqueName() {
// push() without arguments returns a ThennableReference, which we'll abuse for it's key generation
return admin.database().ref().push().key;
}
If you did want the uploaded image to be publicly accessible, you could use the following .on('finish', ...) handler that adds in the File.makePublic() function:
.on('finish', () => {
if (!storageFile) {
res.status(400).json({error: 'expected file'}); // 400 BAD_REQUEST
return;
}
storageFile.makePublic()
.then(() => {
return db.doc(`/users/${req.user.handle}`).update({
imagePath: storageFilepath,
imageUrl: `https://storage.googleapis.com/${config.storageBucket}/${storageFilepath}`
});
})
.then(() => {
res.status(201).json({ message: 'Image uploaded successfully' }); // 201 CREATED
})
.catch((err) => {
console.error(err);
res.status(500).json({ error: err.code }); // 500 INTERNAL_SERVER_ERROR
});
})
Found a solution to the issue!
Essentially - you need to set up your Google Application Credentials. Go into firebase and look into your settings. You need to set up the environment variable GOOGLE_APPLICATION_CREDENTIALS so that firebase has your credentials when you access these files.
https://firebase.google.com/docs/admin/setup?authuser=1 for more information.
After you've done that, check the security settings in firebase, in every area you're dealing with. This should solve the problem (it's definitely a security issue and not your code).
This was the tutorial in question as well for those looking on . https://www.youtube.com/watch?v=m_u6P5k0vP0&t=7661s .
In my case it was wrong bucket Id configured - after correcting that i was able to upload file
I have to send a file to an API, therefor I have to use fs.readFileSync(). After uploading the picture to the storage, I am calling my function to execute the API call. But I cannot get the file from the storage. This is a section of the code, which always gets null in the result. I tried also to .getFiles() without a parameter and then I got all files but I dont want to filter them by iteration.
exports.stripe_uploadIDs = functions.https //.region("europe-west1")
.onCall((data, context) => {
const authID = context.auth.uid;
console.log("request is authentificated? :" + authID);
if (!authID) {
throw new functions.https.HttpsError("not authorized", "not authorized");
}
let accountID;
let result_fileUpload;
let tempFile = path.join(os.tmpdir(), "id_front.jpg");
const options_id_front_jpeg = {
prefix: "/user/" + authID + "/id_front.jpg"
};
const storageRef = admin
.storage()
.bucket()
.getFiles(options_id_front)
.then(results => {
console.log("JPG" + JSON.stringify(results));
// need to write this file to tempFile
return results;
});
const paymentRef = storageRef.then(() => {
return admin
.database()
.ref("Payment/" + authID)
.child("accountID")
.once("value");
});
const setAccountID = paymentRef.then(snap => {
accountID = snap.val();
return accountID;
});
const fileUpload = setAccountID.then(() => {
return Stripe.fileUploads.create(
{
purpose: "identity_document",
file: {
data: tempFile, // Documentation says I should use fs.readFileSync("filepath")
name: "id_front.jpg",
type: "application/octet-stream"
}
},
{ stripe_account: accountID }
);
});
const fileResult = fileUpload.then(result => {
result_fileUpload = result;
console.log(JSON.stringify(result_fileUpload));
return result_fileUpload;
});
return fileResult;
});
Result is:
JPG[[]]
You need to download your file from a bucket to your local function context env.
After your Firebase function start executing you can call the below:
More or less the below should work, just tweak to your needs. Call this within you .onCall context, you get the idea
import admin from 'firebase-admin';
import * as path from 'path';
import * as os from 'os';
import * as fs from 'fs';
admin.initializeApp();
const { log } = console;
async function tempFile(fileBucket: string, filePath: string) {
const bucket = admin.storage().bucket(fileBucket);
const fileName = 'MyFile.ext';
const tempFilePath = path.join(os.tmpdir(), fileName);
const metadata = {
contentType: 'DONT_FORGET_CONTEN_TYPE'
};
// Donwload the file to a local temp file
// Do whatever you need with it
await bucket.file(filePath).download({ destination: tempFilePath });
log('File downloaded to', tempFilePath);
// After you done and if you need to upload the modified file back to your
// bucket then uploaded
// This is optional
await bucket.upload(tempFilePath, {
destination: filePath,
metadata: metadata
});
//free up disk space by realseasing the file.
// Otherwise you might be charged extra for keeping memory space
return fs.unlinkSync(tempFilePath);
}