When I try to upload files to the storage server, it uploads fine. But when I subscribe to the snapshot changes to get the download URL, it throws an error.
Here is my code:
const fileForUpload = this.filesForUpload[0];
this.afStorage
.upload(
fileForUpload.path,
fileForUpload.file,
fileForUpload.metadata
)
.snapshotChanges()
.subscribe(task => {
const downloadUrl = task.ref.getDownloadURL(); // throws error!
});
Here's the error message:
Firebase Storage: Object
'reddit/1532105412851_node_js_hexagon-wallpaper-1920x1080.jpg' does
not exist.
Here's a screenshot if you want more details on the error message:
It says reddit/ because I'm recreating reddit.com for practice.
When I look at my storage on firebase, I see the file uploaded fine.
use the call back function
this.storage.ref(path).putString(this.image, 'data_url').then(data => {
//data in this case contains the download ref
console.log(data) //this will help you see the response
});
Related
I am following the AWS SDK v3 for Javascript guide to display my DynamoDb table names.
https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/welcome.html
However, I am receiving the following error. Any help in understanding why I am receiving this error would be greatly appreciated! :-)
TypeError: Cannot read properties of undefined (reading 'ExclusiveStartTableName')
at serializeAws_json1_0ListTablesInput (C:\source\training\react\portfolio-app\finance_api\node_modules\#aws-sdk\client-dynamodb\dist-cjs\protocols\Aws_json1_0.js:3833:19)
at serializeAws_json1_0ListTablesCommand (C:\source\training\react\portfolio-app\finance_api\node_modules\#aws-sdk\client-dynamodb\dist-cjs\protocols\Aws_json1_0.js:357:27)
at serialize (C:\source\training\react\portfolio-app\finance_api\node_modules\#aws-sdk\client-dynamodb\dist-cjs\commands\ListTablesCommand.js:40:72)
at C:\source\training\react\portfolio-app\finance_api\node_modules\#aws-sdk\middleware-serde\dist-cjs\serializerMiddleware.js:12:27
at C:\source\training\react\portfolio-app\finance_api\node_modules\#aws-sdk\middleware-endpoint\dist-cjs\endpointMiddleware.js:20:16
at async C:\source\training\react\portfolio-app\finance_api\node_modules\#aws-sdk\middleware-logger\dist-cjs\loggerMiddleware.js:5:22
at async listTables (file:///C:/source/training/react/portfolio-app/finance_api/src/helper/listAWSTable.js:6:21)
at async file:///C:/source/training/react/portfolio-app/finance_api/src/helper/runAWSCommands.js:4:1
Here are the contents of the javascript file I am using to extract the list of tables, it's basically copied from the developer-guide.
NB I have substituted in my region and I have AWS credentials loaded in my VSCode.
listAWSTables.js
import { DynamoDBClient, ListTablesCommand } from "#aws-sdk/client-dynamodb";
async function listTables() {
const dbclient = new DynamoDBClient({ region: "ap-southeast-2" });
try {
const results = await dbclient.send(new ListTablesCommand());
results.Tables.forEach(function (item, index) {
console.log(item.Name);
});
} catch (err) {
console.error(err);
}
}
export { listTables };
I call it from another file "runAWSCommands.js":
runAWSCommands.js
import { listTables } from "./listAWSTables.js";
await listTables();
At the commandline I start it off using this command: node runAWSCommands.js
The error:
TypeError: Cannot read properties of undefined (reading 'ExclusiveStartTableName')
It is saying: "The ListTablesCommand cannot read a property from an input that is undefined"
If we look at the definition type of ListTablesCommand:
It expects an input value. If we look at the documentation, we can also see an input variable there.
This input object can be empty, in case you don't want to pass any configuration.
Hence, you can change the line:
const results = await dbclient.send(new ListTablesCommand());
to:
const results = await dbclient.send(new ListTablesCommand({}));
And it should work as expected.
I want to send cloud firestore data to algolia to enable full-text search. Firebase cloud function log is showing an error about application id. I am not able to understand this error and how to fix this.
name: 'RetryError',
message: 'Unreachable hosts - your application id may be incorrect. If the error persists, contact support#algolia.com.'
This is my index.js file
exports.addFirestoreDataToAlgolia =
functions.https.onRequest((req, res) => {
var arr = [];
admin.firestore().collection("tags").get()
.then((docs) => {
docs.forEach((doc) => {
let user = doc.data();
user.objectID = doc.id;
arr.push(user);
})
const client = algoliasearch(ALGOLIA_ID, ALGOLIA_ADMIN_KEY);
const index = client.initIndex(ALGOLIA_INDEX_NAME);
return index.saveObjects(arr, (err, content) => {
if (err) {
res.status(500);
}
else {
res.status(200).send(content);
}
})
})
.catch( err => {
console.log(err);
})
})
Outbound requests (outside of Google services) can only be made from functions on a paid plan (https://firebase.google.com/pricing).
Reason for the wrong appID error is that the Algolia is trying to resolve a dns using your appID, which fails. See https://github.com/algolia/algoliasearch-client-javascript/issues/587#issuecomment-407397688
You have to move off of the free Spark plan in order to call out to Algolia from your function..
I also got this error with NextJS, it was working fine with react but then when I moved to NextJs I got the error.
Turns out it was my .env variables that were not being passed correctly to the client/browser. Renaming the variables from REACT_APP_<variable name> to NEXT_PUBLIC_<variable name> to make them available to the browser as per the NextJs documentation fixed the issue.
NEXT_PUBLIC_ALGOLIA_APP_ID=xxxxxx
NEXT_PUBLIC_ALGOLIA_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
NEXT_PUBLIC_ALGOLIA_ADMIN_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxx
I am writing a firebase cloud function that records the download link of a recentally uploaded file to real-time database:
exports.recordImage = functions.storage.object().onFinalize((object) => {
});
"object" gives me access to two variables "selfLink" and "mediaLink" but both of them when entered in a browser they return the following:
Anonymous caller does not have storage.objects.get access to ... {filename}
So, they are not public links. How can I get the public download link within this trigger function?
You have to use the asynchronous getSignedUrl() method, see the doc of the Cloud Storage Node.js library: https://cloud.google.com/nodejs/docs/reference/storage/2.0.x/File#getSignedUrl.
So the following code should do the trick:
.....
const defaultStorage = admin.storage();
.....
exports.recordImage = functions.storage.object().onFinalize(object => {
const bucket = defaultStorage.bucket();
const file = bucket.file(object.name);
const options = {
action: 'read',
expires: '03-17-2025'
};
// Get a signed URL for the file
return file
.getSignedUrl(options)
.then(results => {
const url = results[0];
console.log(`The signed url for ${filename} is ${url}.`);
return true;
})
});
Note that, in order to use the getSignedUrl() method, you need to initialize the Admin SDK with the credentials for a dedicated service account, see this SO Question & Answer firebase function get download url after successfully save image to firebase cloud storage.
*use this function:
function mediaLinkToDownloadableUrl(object) {
var firstPartUrl = object.mediaLink.split("?")[0] // 'https://storage.googleapis.com/download/storage/v1/b/abcbucket.appspot.com/o/songs%2Fsong1.mp3.mp3'
var secondPartUrl = object.mediaLink.split("?")[1] // 'generation=123445678912345&alt=media'
firstPartUrl = firstPartUrl.replace("https://storage.googleapis.com/download/storage", "https://firebasestorage.googleapis.com")
firstPartUrl = firstPartUrl.replace("v1", "v0")
firstPartUrl += "?" + secondPartUrl.split("&")[1]; // 'alt=media'
firstPartUrl += "&token=" + object.metadata.firebaseStorageDownloadTokens
return firstPartUrl
}
this is how your code might look like:
export const onAddSong = functions.storage.object().onFinalize((object) => {
console.log("object: ", object);
var url = mediaLinkToDownloadableUrl(object);
//do anything with url, like send via email or save it in your database in playlist table
//in my case I'm saving it in mongodb database
return new playlistModel({
name: storyName,
mp3Url: url,
ownerEmail: ownerEmail
})
.save() // I'm doing nothing on save complete
.catch(e => {
console.log(e) // log if error occur in database write
})
})
*I have tested this method on mp3 files, I'm sure it will work on all type of files but incase if it doesnt work for you simply go to firebase storage dashboard open any file and copy download url, and try to generate the same url in your code, and edit this answer too if possible
I get the error "Cannot read property 'buffer' of undefined" if I call the method getToken(), but only on my work notebook.
On my pesonal PC it is working.
Here is my code in the web app created via TypeScript:
this.messaging.requestPermission()
.then(() => {
console.log('Notification permission granted!');
return me.messaging.getToken(); ==> Here I get the error on my work notebook!
})
.then(messagingToken=> {
me.updateMessagingToken(messagingToken);
})
.catch((err) => {
console.log('Unable to get permission to notify.', err);
me.openSnackBar("Unable to get permission to notify!" + err);
})
It seems to me that you may have cached older version of your app. Have you tried (1) clearing the cache, (2) using private mode, (3) using another browser?
In a Firebase cloud function I download an image from one bucket, create a temporary file (to make modifications) and then attempt to upload it to a different bucket. When doing so, the logs show an ApiError: Not found exception when attempting to upload the temporary file. I can upload the temporary file to the bucket the original file came from without issues.
I was under the assumption that the temporary file was stored in memory but it seems it is somehow linked to the original bucket... Any ideas?
const file = gcs.bucket(object.bucket).file(object.name); //OBJECT IS FROM THE TRIGGER EVENT
const tempLocalFilename = `/tmp/${path.parse(file.name).base}`;
// Download file from bucket.
return file.download({ destination: tempLocalFilename })
.catch((err) => {
console.error('Failed to download file.', err);
return Promise.reject(err);
})
.then(() => {
console.log(`Image ${file.name} has been downloaded to ${tempLocalFilename}.`);
// UPLOADING TO ORIGINAL FILE BUCKET WORKS
return file.bucket.upload(tempLocalFilename, { destination: "test.jpg"
})
// USING THE BELOW INSTEAD RESULTS IN A NOT FOUND EXCEPTION
const newbucket = gcs.bucket("squarenotch-imageserver");
return newbucket.upload(tempLocalFilename, { destination: "test.jpg"})