Cannot get Url from filebase storage? - javascript

I am trying to retrieve data url from firebase storage. I have a static function to get url, but the return is always undefined? How can I get the url of the file and store to my database?
uploadImageByDataURL(image, imageName, directory) {
const uploadTask = firebase.storage().ref(`images/${directory}/${imageName}`).putString(image, 'data_url');
uploadTask.on('state_changed', () => {
firebase.storage().ref(`images/${directory}`).child(`${imageName}`).getDownloadURL().then(url => {
return url
})
})
}

Retrieving the download URL happens asynchronously. Any code that requires the download URL, should be in the corresponding then() block. So:
const uploadTask = firebase.storage().ref(`images/${directory}/${imageName}`).putString(image, 'data_url');
uploadTask.on('state_changed', () => {
firebase.storage().ref(`images/${directory}`).child(`${imageName}`).getDownloadURL().then(url => {
firebase.database().reference().set(url);
})
})

Related

ionic Angular 9 wait until file download url is available

I am using ionic 5 and angular 9 to upload a data url to firebase storage. My code works good but i am not sure how to wait until the download url is avaialble.
below is the code
uploadToFireStore(imageData){
const storage = getStorage();
const storageRef = ref(storage, (new Date().getTime().toString()));
uploadString(storageRef, imageData, 'data_url').then((snapshot) => {
getDownloadURL(snapshot.ref).then((downloadURL) => {
console.log('File available at', downloadURL);
this.downloadURL = downloadURL
});
});
}
I am calling it in my camera plugin like this
this.uploadToFireStore(base64Image)
console.log("updated with url:", this.downloadURL)
currently the download url is printed later and my code is not waiting for download url to be there. I need this url to upload to my RTDB so please advise how can i do it without moving the code into this part
getDownloadURL(snapshot.ref).then((downloadURL) => {
...
You probably just need to return your promise chain:
uploadToFireStore(imageData){
const storage = getStorage();
const storageRef = ref(storage, (new Date().getTime().toString()));
return uploadString(storageRef, imageData, 'data_url').then((snapshot) => {
return getDownloadURL(snapshot.ref).then((downloadURL) => {
console.log('File available at', downloadURL);
this.downloadURL = downloadURL
});
});
}
Then you can do this:
this.uploadToFireStore(base64Image).then(() => {
console.log("updated with url:", this.downloadURL)
});

react firebase image post 400 error on uploading

I am trying to upload an image to a cloud storage and received an post 400 error
The file is in initialize in another component.
Thanks for help
const projectStorage = getStorage();
useEffect(() => {
const storageRef = ref(projectStorage, file.name);
uploadBytes(storageRef, file).then((snap) => {
let percentage = (snap.bytesTransferred / snap.totalBytes) * 100;
setProgress(percentage);
console.log('File Uploaded');
}, (err) => {
setError(err);
}, async () => {
//this url doesnt change the setstate url becuase it is in seperate score
const url = await storageRef.getDownloadURL();
setUrl(url);
})
}, [file]);
I created a new project on firebase and then change the permissions on the storage rules and its works.

Upload .vhd as Page-Blob to azure-blob-storage from Url

i have a bunch of VHD files stored on a private Server, which are accessible through a url.
I am trying upload these vhd files directly to my azure storage account using the azure javascript npm libraries. The vhds have to be uploaded as page-blobs. I tried using the method uploadPagesFromURL() of the pageblobClient but with no success. My code looks roughly like this:
async function uploadVHD(accessToken, srcUrl)
{
try {
// Get credentials from accessToken
const creds = new StorageSharedKeyCredential(storageAccount.name, storageAccount.key);
// Get blobServiceClient
const blobServiceClient = new BlobServiceClient(`https://${storageAccount.name}.blob.core.windows.net`, creds);
// Create Container
const containerClient = blobServiceClient.getContainerClient("vhd-images");
await containerClient.createIfNotExists();
const src = srcUrl.replace('https://', 'https://username:password#');
// Upload to blob storage
const pageBlobClient = containerClient.getPageBlobClient("Test.vhd");
// Get fileSize of vhd
const fileSize = (await axiosRequest(src, { method: "HEAD" })).headers["content-length"];
const uploadResponse = await pageBlobClient.uploadPagesFromURL(src, 0, 0, fileSize);
return uploadResponse;
} catch (error) {
return error;
}
});
It is not possible to upload the Page Blob with your URL directly. You need to read data from the url. Then upload using uploadPages method.
axios.get(URL, {
responseType: 'arraybuffer'
})
.then((response) => {
console.log(response.data)
console.log(response.data.length)
// upload page blob...
}).catch((error) => {
//handle error
});
// uploadPages method
const uploadResponse = pageBlobClient.uploadPages(data, 0, dataLength);

Expand my image upload from 1 to 5 photos; map/foreach?

I am creating an app in which you can upload a photo, with some other data, to Firebase. The uploading part worked perfect with one picture. However I have now added a multiple-image picture (select 1 to 5 pictures) and would like my image upload function to upload the 5 pictures in stead of the 1.
The image upload works with 1 image provided, so how can I rearrange my code to upload the x-amount of photos in the array?
The pictures are added in the photos array with the following data (output shown below is a console.log from the images fetched);
Array [
Object {
"exists": true,
"file": "ph://8905951D-1D94-483A-8864-BBFDC4FAD202/L0/001",
"isDirectory": false,
"md5": "f9ebcab5aa0706847235887c1a7e4740",
"modificationTime": 1574493667.505371,
"size": 104533,
"uri": "ph://8905951D-1D94-483A-8864-BBFDC4FAD202/L0/001",
},
With this didFocus I check if the fethedImages param is set and set the photos array to the fetched images (So all the data that is shown above)
const didFocusSubscription = props.navigation.addListener(
'didFocus', () => {
let fetchedImages = props.navigation.getParam('fetchedImages')
console.log(fetchedImages)
setPhotos(fetchedImages)
setImageValid(true)
calculateImageDimensions()
}
);
When I save the page and start dispatching the data I run the following command the uploadImage function is ran and returns an uploadurl, this is then saved later on in the dispatch function to the Firebase Database to be fetched later;
uploadurl = await uploadImageAsync(photos)
SO the uploadImageAsync starts with the photos array forwarded. How can I make sure the function below is started for every photo.uri in the array? Can I use .map of for each for this, and in what context should I be using this?
Also I am not quite sure how I can send back an array of URLs to be saved together with the rest of the information.
async function uploadImageAsync(photos) {
console.log('uploadImage is gestart')
// Why are we using XMLHttpRequest? See:
// https://github.com/expo/expo/issues/2402#issuecomment-443726662
const blob = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function () {
resolve(xhr.response);
};
xhr.onerror = function (e) {
console.log(e);
reject(new TypeError('Network request failed'));
};
xhr.responseType = 'blob';
xhr.open('GET', photos, true);
xhr.send(null);
});
const ref = firebase
.storage()
.ref()
.child(uuid.v4());
const snapshot = await ref.put(blob);
// We're done with the blob, close and release it
blob.close();
return await snapshot.ref.getDownloadURL();
}
==============edited because of progress with uploading====================
Once again I am a little bit further. However the image upload function is now running, and because of is being multiple images I would like to await the response of all the images before continuing.
try {
uploadurl = await uploadImageAsync()
address = await getAddress(selectedLocation)
console.log(uploadurl)
if (!uploadurl.lenght) {
Alert.alert('Upload error', 'Something went wrong uploading the photo, plase try again', [
{ text: 'Okay' }
]);
return;
}
dispatch(
At this moment when I start the uploadImageAsync function. With he help of console.log I see it uploading the images, they also show up online. But while the pictures are uploading the upload url already returns with 0 and shows the Alert and stops the function.
uploadImageAsync = async () => {
const provider = firebase.database().ref(`providers/${uid}`);
let imagesArray = [];
try {
await photos.map(img => {
let file = img.data;
const path = "Img_" + uuid.v4();
const ref = firebase
.storage()
.ref(`/${uid}/${path}`);
ref.putString(file).then(() => {
ref
.getDownloadURL()
.then(images => {
imagesArray.push({
uri: images
});
console.log("Out-imgArray", imagesArray);
})
return imagesArray <== this return imagesArray is fired to early and starts the rest of my upload function.
} catch (e) {
console.error(e);
}
};
So a Discord chat pointed me in the way of a promise.all function for this to work. I tried that, but opened another stack overflow topic for getting this to work.
await response of image upload before continue function
The solution for my image upload function is in the topic above;
uploadImages = () => {
const provider = firebase.database().ref(`providers/${uid}`);
// CHANGED: removed 'let imagesArray = [];', no longer needed
return Promise.all(photos) // CHANGED: return the promise chain
.then(photoarray => {
console.log('all responses are resolved successfully');
// take each photo, upload it and then return it's download URL
return Promise.all(photoarray.map((photo) => { // CHANGED: used Promise.all(someArray.map(...)) idiom
let file = photo.data;
const path = "Img_" + uuid.v4();
const storageRef = firebase // CHANGED: renamed 'ref' to 'storageRef'
.storage()
.ref(`/${uid}/${path}`);
let metadata = {
contentType: 'image/jpeg',
};
// upload current photo and get it's download URL
return storageRef.putString(file, 'base64', metadata) // CHANGED: return the promise chain
.then(() => {
console.log(`${path} was uploaded successfully.`);
return storageRef.getDownloadURL() // CHANGED: return the promise chain
.then(fileUrl => ({uri: fileUrl}));
});
}));
})
.then((imagesArray) => { // These lines can
console.log("Out-imgArray: ", imagesArray) // safely be removed.
return imagesArray; // They are just
}) // for logging.
.catch((err) => {
console.error(err);
});
};

firebase storage, retrieving an image to a vue app

I am trying to download an image from my firebase storage to render it in my Vue app, the upload from the application to the firebase storage is successful, however upon retrieval it gives me an error, i am using the firebase SDK in a Vue CLI 3 setup and vuex to manage my state. Here is the function setting in my actions in the main store.js file
createMeetUp({commit, getters}, payload) {
//here my payload is an object contains the following props
const meetup = {
title: payload.title,
location: payload.location,
date: payload.date.toISOString(),
description: payload.description,
creatorId: getters.user.id
}
let imageUrl
let key
//now i am reaching out to the firebase database to store the above object
firebase.database().ref('meetup').push(meetup)
.then(data => {
key = data.key
return key
})
.then(key => {
//also in my payload object i stored an image file
//so here i am uploading the image to the firebase storage
const fileName = payload.image.name
const extension = fileName.slice(fileName.lastIndexOf('.'))
return firebase.storage().ref('meetup/' + key + '.' + extension).put(payload.image)
})
.then(imageInfo => {
//the issue is here in this then() block as i am stuck on how to retrieve the image from the storage to render it in the app
imageUrl = imageInfo.getDownloadURL()
return firebase.database().ref('meetups').child(key).update({
imageUrl: imageUrl
})
})
.then(() => {
//here i am simply commiting my mutation..
commit('createMeetUp', {
...meetup,
imageUrl: imageUrl,
id : key
})
})
.catch(err => console.log(err))
}
the error I am getting is:
TypeError: imageInfo.getDownloadURL is not a function
Again I believe the issue is in the then() block where I retrieve the image from the firebase storage.
thanks in advance
Following the comments above, the following should work if I am not mistaking (not tested...).
Note that getDownloadURL() returns a promise (see here), therefore you have to chain the promises.
....
.then(key => {
//also in my payload object i stored an image file
//so here i am uploading the image to the firebase storage
const fileName = payload.image.name
const extension = fileName.slice(fileName.lastIndexOf('.'))
return firebase.storage().ref('meetup/' + key + '.' + extension).put(payload.image)
})
.then(uploadTaskSnapshot => {
return uploadTaskSnapshot.ref.getDownloadURL()
})
.then(imageUrl => {
return firebase.database().ref('meetups').child(key).update({
imageUrl: imageUrl
})
})
....

Categories

Resources