Storing multiple images into firebase and getting urls - firebase

I have 100 images that I want to store in firebase storage, but I also need to extract the urls from them. Is there an automatic way of doing it?
If not is there a better service provider that allows uploading a lot of images and extracting the url all automatically??

I highly recommend using Firebase Storage and the Firebase Realtime Database together to accomplish this. Some code to show how these pieces interact is below (Swift):
Shared:
// Firebase services
var database: FIRDatabase!
var storage: FIRStorage!
...
// Initialize Database, Auth, Storage
database = FIRDatabase.database()
storage = FIRStorage.storage()
Upload:
let fileData = NSData() // get data...
let storageRef = storage.reference().child("myFiles/myFile")
storageRef.putData(fileData).observeStatus(.Success) { (snapshot) in
// When the image has successfully uploaded, we get it's download URL
// This "extracts" the URL, which you can then save to the RT DB
let downloadURL = snapshot.metadata?.downloadURL()?.absoluteString
// Write the download URL to the Realtime Database
let dbRef = database.reference().child("myFiles/myFile")
dbRef.setValue(downloadURL)
}
Download:
let dbRef = database.reference().child("myFiles")
dbRef.observeEventType(.ChildAdded, withBlock: { (snapshot) in
// Get download URL from snapshot
let downloadURL = snapshot.value() as! String
// Create a storage reference from the URL
let storageRef = storage.referenceFromURL(downloadURL)
// Download the data, assuming a max size of 1MB (you can change this as necessary)
storageRef.dataWithMaxSize(1 * 1024 * 1024) { (data, error) -> Void in
// Do something with downloaded data...
})
})
For more information, see Zero to App: Develop with Firebase, and it's associated source code, for a practical example of how to do this.

Related

How can i get Image URL from Firebase Storage to Firebase Database without uploading image from my app?

I upload one image from my computer to Firebase Storage and now I want that image to get in my Firebase database with his information and display it in my app. I can display information but cant display images. I google also but in every answer, they say first to upload the image to firebase storage from the app. then get his URL in the database and I don't want to upload from my app.
So if someone know then help.
You Can Get the download link for your image Like this
static final firebase_storage.FirebaseStorage storage =
firebase_storage.FirebaseStorage.instance;
String url = await storage
.ref('YourImagePath')
.getDownloadURL();
In addition to SARADAR21's excellent answer on how to get the data for a file at a known path, you can also list the files in Cloud Storage through the API, in case you don't know the path.
From that documentation:
final storageRef = FirebaseStorage.instance.ref();
final listResult = await storageRef.listAll();
for (var prefix in listResult.prefixes) {
// The prefixes under storageRef.
// You can call listAll() recursively on them.
}
for (var item in listResult.items) {
// The items under storageRef.
}
You can then use the references you get this way, and call getDownloadUrl() to get a download URL for each of them.
Future<QuerySnapshot?> getDataFromFirebase() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
FirebaseFirestore.instance
.collection('Images')
.get()
.then((QuerySnapshot? querySnapshot) {
querySnapshot!.docs.forEach((doc) {
List<dynamic> allImageData = doc["image_data"];
storeImageList = allImageData.map((i) => i.toString()).toList();
});
prefs.setStringList("imageList", storeImageList);
});
}

Flutter : How to upload image to firestore in form

Hay, I'm new in firestore and a little bit confused about uploading data to firestore. let's take an example, I have a form format like this :
so, there is a data (name, DoB) form and upload image form. as far I know is to store data collection (like name and Date of Brith section) is using the cloud_firestore plugin, otherwise to store the image file is using firebase_store plugin.
then, how do I use both plugins at the same time when uploading forms like this? or is there another method to upload image with a form?
Thanks.
You need to first upload the image to firebse_storage , get a link and create the firestore document.
example
// upload the file helper
Future<String?> uploadFile(FilePickerResult? fileName) async {
Uint8List? fileBytes = fileName!.files.first.bytes;
// Create a Reference to the file
var filename = DateTime.now().toLocal().toIso8601String();
if (kIsWeb) {
firebase_storage.Reference ref = firebase_storage.FirebaseStorage.instance
.refFromURL(storageRefFbS)
.child("files")
.child(filename + "." + fileName.files.first.extension!);
await ref.putData(fileName.files.first.bytes!);
var dwonloadurl = await ref.getDownloadURL();
log(dwonloadurl);
return dwonloadurl;
}
}
//upload a file/image
var downloadUrl =
await firebaseHelper.uploadFile(myPickedFile);
// save the data
FirebaseFirestore.instance
.collection("myData")
.set({
"sname": "name",
"url":downloadUrl,
});

How to ensure file integrity in Google Cloud Firebase Storage?

I am writing a web service where users can upload and download files to their user directory in Google Cloud Firebase Storage.
Imagine a user uploads a 1GB file to the storage. While the user uploads the file, it is already visible by other "processes".
What are common techniques to identify a file being uploaded 100% from a process that does not have the upload stats?
One approach in a local environment would be to call the file first "my-file.iso.tmp" and later rename them by removing the suffix, since a rename operation is atomic. But that doesn't seem to be a suitable solution for my Firebase Storage problem.
Any insights are highly appreciated!
There isn't any method to rename a file in Firebase storage. If you want to show realtime upload stats across all user's devices then using realtime database could be a way.
var uploadTask = storageRef.child('images/rivers.jpg').put(file);
uploadTask.on('state_changed',
async (snapshot) => {
var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log('Upload is ' + progress + '% done');
await updateUploadStatus(progress)
}
},
(error) => {
// Handle unsuccessful uploads
},
() => {
// Upload completed
await uploadStatus(100)
uploadTask.snapshot.ref.getDownloadURL().then((downloadURL) => {
console.log('File available at', downloadURL);
});
}
);
async function updateUploadStatus(progress) {
const dbRef = firebase.database().ref(`users/${userID}/${fileID}`)
await dbRef.update(progress)
}
The updateUploadStatus will update progress to realtime database and you can listen it on all other devices where user has logged in (and is active) as follows:
var fileRef = firebase.database().ref(`users/${userID}/${fileID}`);
fileRef.on('value', (snapshot) => {
const data = snapshot.val();
updateFileProgress(data);
});
It's upto you how you get that fileID on other devices or you could listen to users/${userID} node itself. While the progress is not 100 percent you can grey out that file icon or something like that.

Cloud Functions: zip multiple documents from Cloud Storage

I already searched through a lot of questions on stack overflow but couldn't find a fitting answer from which I can derive the answer I need:
I want to zip multiple files from a folder within Google Cloud Storage/Firebase Storage with a Cloud Function.
I already found the solution for zipping documents from the local filesystem but could not derive how to do it within a Cloud Function for Cloud Storage.
Google Cloud Storage supports the decompressive form of transcoding but not a compressive form of transcoding. However, at Cloud Storage, any user can store a gzip-compressed file.
To zip multiple documents from Cloud Storage using Cloud Functions, you can download the files from Cloud Storage to functions instances using gcs.bucket.file(filePath). download, zip the file, and re-upload the files to the Cloud Storage. Here you will find an example of downloading, transforming, and uploading a file. You can find an example to zip multiple files in this StackOverflow thread. This document explains how you can upload objects to Cloud Storage using Console, Gsutil, Code Sample, or REST APIs.
A bit late, but I had the same problem to solve.
The following Firebase Function:
Runs with 1 GB / 120 seconds timeout (for good measure)
Is triggered by WRITE calls (do this only if you have few calls!)
Ignores all paths except background_thumbnail/
Creates a random working directory and deletes it afterwards
Downloads images from Firebase Storage
Zips these images in a folder: background_thumbnail/<IMAGE>
Uploads created ZIP to Firebase Storage
Creates a signed URL for the ZIP file at Firebase Storage
Stores the signed URL in Firestore.
The code can probably be improved and made more elegant, but it works (for now).
const {v4: uuidv4} = require("uuid"); // for random working dir
const JSZip = require("jszip");
exports.generateThumbnailZip = functions
.runWith({memory: "1GB", timeoutSeconds: 120})
.region("europe-west3")
.storage.object()
.onFinalize(async (object) => {
// background_thumbnail/ is the watched folder
if (!object.name.startsWith("background_thumbnail/")) {
return functions.logger.log(`Aborting, got: ${object.name}.`);
}
const jszip = new JSZip();
const bucket = admin.storage().bucket();
const fileDir = path.dirname(object.name);
const workingDir = path.join(os.tmpdir(), uuidv4());
const localZipPath = path.join(workingDir, `${fileDir}.zip`);
const remoteZipPath = `${fileDir}.zip`;
await mkdirp(workingDir);
// -------------------------------------------------------------------
// DOWNLOAD and ZIP
// -------------------------------------------------------------------
const [files] = await bucket.getFiles({prefix: `${fileDir}/`});
for (let index = 0; index < files.length; index++) {
const file = files[index];
const name = path.basename(file.name);
const tempFileName = path.join(workingDir, name);
functions.logger.log("Downloading tmp file", tempFileName);
await file.download({destination: tempFileName});
jszip.folder(fileDir).file(name, fs.readFileSync(tempFileName));
}
const content = await jszip.generateAsync({
type: "nodebuffer",
compression: "DEFLATE",
compressionOptions: { level: 9 }
});
functions.logger.log("Saving zip file", localZipPath);
fs.writeFileSync(localZipPath, content);
// -------------------------------------------------------------------
// UPLOAD ZIP
// -------------------------------------------------------------------
functions.logger.log("Uploading zip to storage at", remoteZipPath);
const uploadResponse = await bucket
.upload(path.resolve(localZipPath), {destination: remoteZipPath});
// -------------------------------------------------------------------
// GET SIGNED URL FOR ZIP AND STORE IT IN DB
// -------------------------------------------------------------------
functions.logger.log("Getting signed URLs.");
const signedResult = await uploadResponse[0].getSignedUrl({
action: "read",
expires: "03-01-2500",
});
const signedUrl = signedResult[0];
functions.logger.log("Storing signed URL in db", signedUrl);
// Stores the signed URL under "zips/<WATCHED DIR>.signedUrl"
await db.collection("zips").doc(fileDir).set({
signedUrl: signedUrl,
}, {merge: true});
// -------------------------------------------------------------------
// CLEAN UP
// -------------------------------------------------------------------
functions.logger.log("Unlinking working dir", workingDir);
fs.rmSync(workingDir, {recursive: true, force: true});
functions.logger.log("DONE");
return null;
});

Delete Firebase Storage image url with download url

I am using Firebase storage and Realtime Database for storing the image and its download url respectively.The filename is generated in a random manner with which download url is generated and saved to the realtime database.
Scenario:
If user uploads new Image(For e.g Profile Image) I want to delete the old image with the help of downloadImageurl(Download image url is generated when image is uploaded initially and same is saved in the realtime database).How the old image can be deleted?I have tried below code but for it to work I must get filename.
gcs
.bucket("e**********.appspot.com") // find it in Firebase>Storage>"gs://...." copy without gs
//or go to console.cloud.google.com/ buckets and copy name
.file("images/" +event.params.uid+"/"+filename) //file location in my storage
.delete()
.then(() => {
console.log(`gs://${bucketName}/${filename} deleted.`);
})
.catch(err => {
console.error('ERROR-DELETE:', err+ " filename: "+filename);
});
This may help you out.
This code will fetch the name of file from the URL and will delete that file. Currently this solution works for me!
Code
import * as firebase from 'firebase';
...
let name = imagePath.substr(imagePath.indexOf('%2F') + 3, (imagePath.indexOf('?')) - (imagePath.indexOf('%2F') + 3));
name = name.replace('%20',' ');
let storagePath = firebase.storage().ref();
storagePath.child(`images/${name}`).delete();
Depending on what you want:
Keep the original image and being able to delete it manually in the future.
Delete it immediately after the thumbnail is generated.
I suppose you are using this example
1- You have to store the filePath in your db. Then whenever you want to delete it from your front:
import * as firebase from 'firebase';
...
const store = firebase.storage().ref();
// Depending on which db you use and how you store, you get the filePath and delete it:
store.child(image.filePath).delete();
2- Continue the promise from the firebase function like this:
// ...LAST PART OF THE EXAMPLE...
.then(() => {
// Add the URLs to the Database
return admin.database().ref('images').push({path: fileUrl, thumbnail: thumbFileUrl});
}).then(() => {
// ...PART YOU CAN ADD TO DELETE THE IMAGE UPLOADED
const bucket = gcs.bucket(bucket);
bucket.file(filePath).delete();
})
"bucket" is the const previously created:
const bucket = gcs.bucket(event.data.bucket);
as well as "filePath":
const filePath = event.data.name;
To delete an image with the url, you can use refFromUrl() function to get the ref then delete it easily
const storage = firebase.storage();
storage.refFromURL(imageUrl).delete()
const downloadUrl = "https://firebasestorage.googleapis.com/v0/b/***.appspot.com/o/***?alt=media&token=***";
The first *** represents FIREBASE_STORAGE_BUCKET
The second *** represents location of file in bucket
The third *** represents token for public access image/file
As a web developer, you're aware that URI are encoded such as
"#" = "%40",
"$" = "%24",
" " = "%20", etc.
Since we are using JavaScript, what we can do is decode URI like so to get exact path
const path = decodeURIComponent(downloadUrl.split("o/")[1].split("?")[0]);
return await bucket
.file(path)
.delete()
.then(() => true)
.catch((error) => {
throw new TypeError(`deleteImages ${error}`);
});

Resources