How to get the new download URL after Firebase Extensions Resize Images with AngularFire?

1.7k views Asked by At

Need help in getting the resize image URL after the Firebase extension resizes the image.

Before I was able to do so with the code below. But, after activating the function, images are not showing up. After comparing the imgURL on Firestore and the download URL on Firebase storage, it seems that the functions added image dimensions (500x500) to the back of the pathname. (image_123 -> image_123_500x500).

  1. I've tried looking up on how I can exclude that on the Firebase Extension settings. But no luck. (Might miss it)

  2. I figure that the next option is to just tweak the code itself by getting the URL after the image resized. But I'm either getting undefined or error. Plus I can't figure out implementing without creating two separate functions by "Upload the image first" then "Submit Form".

      upload($event: any) {
        this.file = $event.target.files[0];
        this.image = true;
      }


        async submitHandler() {
        if (this.image === true) {
          // Generate random ID
          const randomId = Math.random().toString(36).substring(2);
          // The storage path
          const path = `products/${this.productForm.value.model}_${randomId}`;
          // Reference to storage bucket
          const ref = this.afStorage.ref(path);
          // The main task (upload Image to Firestorage)
          this.task = this.afStorage.upload(path, this.file);
    
          // Get the URL from ref (Firestorage), added to the form and submit to FIrestore
          this.task
            .snapshotChanges()
            .pipe(
              finalize(async () => {
                this.downloadURL = await ref.getDownloadURL().toPromise();
                /*this.afs
                .collection('products')
                .add({ downloadURL: this.downloadURL, path });*/
                this.loading = true;
                this.productForm.value.imgUrl = this.downloadURL;
                this.productForm.value.user = this.auth.getUserEmail();
                const formValue = this.productForm.value;
                try {
                  await this.afs.collection('products').add(formValue);
                  console.log(formValue);
                  this.success = true;
                } catch (err) {
                  console.error(err);
                }
              })
            ) // To display URL
            .subscribe();
    
          this.loading = false;
        } else {
          alert('Please upload the picture of product');
        }
      }
2

There are 2 answers

2
gso_gabriel On BEST ANSWER

Indeed, the Resize Image extension will add the height and width to the name of the file, as stated in the official documentation here. As clarified in this answer here, once you installed the extension, it asked you to provide a path for where the files resized will be stored. So, for you to return the downloadURL, it will depend on the name you add for the path or if you didn't add any.

For this reason, you will need to reference the file from the path you set when installing the extension. You will need then, to work on the name of the file, based in the size you set for the new dimensions. You can try following in a way you will add the dimensions to the name of the file. The below code is based in this answer here, that I believe that should help you as a starting point.

function resizedName(fileName, dimensions = '500x500') {
  const extIndex = fileName.lastIndexOf('.');
  const ext = fileName.substring(extIndex);
  return `${fileName.substring(0, extIndex)}_${dimensions}${ext}`;
}

To summarize, you will need to work on the new path to return the files there and in case they are in the same path as the original ones, you will need to modify the name of them, adding the width and height to the names.

0
toTheBestOfMyKnowledge On

We should combine 2 methods provided by firebase for this.

3 Points to note.

  1. Here we are assuming we have the actual image URL or actual image path in firebase storage
  2. We have to know where our new resized images is stored relative to the currentURL.
  3. By taking the filepath of Actual image,we will getDownloadURL of new resized images.
  1. httpsReferencePath --For taking file path from httpURL from firebase
  2. A string Manipulation/Edit Method -- for editing file path
  3. getDownloadURL --For taking file path from httpURL from firebase
import { getStorage, ref, getDownloadURL } from "firebase/storage";

Below is a JS function to get new firebase resized URL.

  async getResizedURL(originalUrl,size) {
    let storageUrl = originalUrl; //originalUrl have the ORIGINAL IMAGE FIREBASE HTTP PATH. Ex: "https://firebasestorage.googleapis.com/v0/b/your-storage-bucket/o/example.jpg?alt=media&token=your-download-token"


    const storage = getStorage();
    const httpsReferencePath = ref(storage, storageUrl).fullPath;//For taking File path of actual image

    const sizeRequired = size; //size is a string which you have provided during extension configuration.Ex:'200x200' or '100x100'
    const newFilePath=this.getNewFilePath(httpsReferencePath);//Return a new string .This should be string manipulation method.If you have created a new folder for resized images.Say "resized-images" is the folder name which have all the resized-images.Add "resized-images" in the folder path.

    const extension=getFileNameExtension(httpsReferencePath);//Again a string manipulation function which pops out last extension
    const newResizedPath = `${newFilePath}_${sizeRequired}.${extension}`;

    await getDownloadURL(ref(storage, newResizedPath)).then((url) => {
      this.resizedImageUrlLink=url; //This URL contains new firebase storage URl for resized image.
    }).catch(()=>{
      this.resizedImageUrlLink=this.url; //return old url itself if any error
    })
  }

Please Note:

const httpsReferencePath = ref(storage, storageUrl).fullPath;//This step is only required if you only have the firebase URL of actual IMAGE.If you have actual file path of stored original image,We don't have to take path and we can directly go find new file path using string manipulation.

Below is a simple extension finder from path.I did not explain it here since its not the focus.Similar string manipulation can be return for the getNewFilePath function also

getFileNameExtension(string){
  return string.split(".").pop();//get last part after last dot in the filepath
}

Refer this link Firebase Storage Ref Doc of firebase documentation which describes the methods available for taking reference of firebase urls.