Firebase storage using cloud function only svg upload not working other format's are okay using base64

Viewed 319

So I and my team are trying really hard to upload and retrieve SVG to firebase storage using cloud functions. With the function that we have built, we are able to upload any image we want except for SVG. For some reason SVG is not working I don't know if we are encoding it wrong or something

Here is my function file

const admin = require("firebase-admin");
const { nanoid } = require("nanoid");
const mime = require("mime-types");
const { validateCauseImageFile } = require("./fileTypeUtils");
const { imageStorageUrlMatch } = require("./regularExpression");

module.exports.imageValidationAndUpload = async (image) => {
  try {
    console.log("Image in base 64", image);
    const bucket = admin.storage().bucket();
    const mimeType = image.match(/data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+).*,.*/)
      ? image.match(/data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+).*,.*/)[1]
      : null;
    const fileExtension = mime.extension(mimeType);
    console.log(fileExtension);
    const fileName = nanoid() + `.${fileExtension}`;
    console.log("Mime type", mimeType);
    const base64EncodedImageString = image.replace(
      /^data:image\/\w+;base64,/,
      ""
    );
    const imageBuffer = Buffer.from(base64EncodedImageString, "base64");
    const result = await validateCauseImageFile(imageBuffer.length, mimeType);

    if (result.success) {
      const token = nanoid();
      const options = {
        gzip: true,
        metadata: {
          contentType: mimeType,
          metadata: {
            firebaseStorageDownloadTokens: token,
          },
        },
      };
      const filePath = "testSvg/" + fileName;
      const file = bucket.file(filePath);
      await file.save(imageBuffer, options);
      const response = await file.getSignedUrl({
        action: "read",
        expires: "03-17-2025", // this is an arbitrary date
      });
      return { success: true, response: response[0] };

      //   return response;
    } else if (image.match(imageStorageUrlMatch)) {
      return { success: true, url: image };
    } else {
      const errorObject = { status: 403, message: result.message };
      throw errorObject;
    }
  } catch (err) {
    console.log("show error message : ", err.message);
    return { success: false, message: err.message };
  }
};

If I upload a png/jpeg/jpg image then it will be uploaded and work fine but for SVG it will be uploaded but won't render anything. On the firebase storage console bucket this is how it shows up

For SVG image

enter image description here

For png or any other image

enter image description here

The upload process works fine but SVG is not rendering or being retrieved properly. Here are the URL's for both files

SVG: https://firebasestorage.googleapis.com/v0/b/infaque-playground.appspot.com/o/testSvg%2FaxOmCbg7IY6Q8q8P-5c6D.svg?alt=media&token=6UXNtvtP_ONzQTkmbWypD

PNG: https://firebasestorage.googleapis.com/v0/b/infaque-playground.appspot.com/o/testSvg%2FsbbcDN_8zIpWLfuDyWEYw.png?alt=media&token=I_YsAVHXC3eMIrdGmIiPY

1 Answers

According to your screenshot, the SVG image is transferred as Content-Type image/svg+xml.

According to your code, this content type is calculated as follows:

const mimeType = image.match(/data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+).*,.*/)
      ? image.match(/data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+).*,.*/)[1]
      : null;

It means that your image data URL should be something like this:

data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDEwMCAxMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiIGhlaWdodD0iMTAwcHgiIHdpZHRoPSIxMDBweCI+CjxnPgoJPHBhdGggZD0iTTI4LjEsMzYuNmM0LjYsMS45LDEyLjIsMS42LDIwLjksMS4xYzguOS0wLjQsMTktMC45LDI4LjksMC45YzYuMywxLjIsMTEuOSwzLjEsMTYuOCw2Yy0xLjUtMTIuMi03LjktMjMuNy0xOC42LTMxLjMgICBjLTQuOS0wLjItOS45LDAuMy0xNC44LDEuNEM0Ny44LDE3LjksMzYuMiwyNS42LDI4LjEsMzYuNnoiLz4KCTxwYXRoIGQ9Ik03MC4zLDkuOEM1Ny41LDMuNCw0Mi44LDMuNiwzMC41LDkuNWMtMyw2LTguNCwxOS42LTUuMywyNC45YzguNi0xMS43LDIwLjktMTkuOCwzNS4yLTIzLjFDNjMuNywxMC41LDY3LDEwLDcwLjMsOS44eiIvPgoJPHBhdGggZD0iTTE2LjUsNTEuM2MwLjYtMS43LDEuMi0zLjQsMi01LjFjLTMuOC0zLjQtNy41LTctMTEtMTAuOGMtMi4xLDYuMS0yLjgsMTIuNS0yLjMsMTguN0M5LjYsNTEuMSwxMy40LDUwLjIsMTYuNSw1MS4zeiIvPgoJPHBhdGggZD0iTTksMzEuNmMzLjUsMy45LDcuMiw3LjYsMTEuMSwxMS4xYzAuOC0xLjYsMS43LTMuMSwyLjYtNC42YzAuMS0wLjIsMC4zLTAuNCwwLjQtMC42Yy0yLjktMy4zLTMuMS05LjItMC42LTE3LjYgICBjMC44LTIuNywxLjgtNS4zLDIuNy03LjRjLTUuMiwzLjQtOS44LDgtMTMuMywxMy43QzEwLjgsMjcuOSw5LjgsMjkuNyw5LDMxLjZ6Ii8+Cgk8cGF0aCBkPSJNMTUuNCw1NC43Yy0yLjYtMS02LjEsMC43LTkuNywzLjRjMS4yLDYuNiwzLjksMTMsOCwxOC41QzEzLDY5LjMsMTMuNSw2MS44LDE1LjQsNTQuN3oiLz4KCTxwYXRoIGQ9Ik0zOS44LDU3LjZDNTQuMyw2Ni43LDcwLDczLDg2LjUsNzYuNGMwLjYtMC44LDEuMS0xLjYsMS43LTIuNWM0LjgtNy43LDctMTYuMyw2LjgtMjQuOGMtMTMuOC05LjMtMzEuMy04LjQtNDUuOC03LjcgICBjLTkuNSwwLjUtMTcuOCwwLjktMjMuMi0xLjdjLTAuMSwwLjEtMC4yLDAuMy0wLjMsMC40Yy0xLDEuNy0yLDMuNC0yLjksNS4xQzI4LjIsNDkuNywzMy44LDUzLjksMzkuOCw1Ny42eiIvPgoJPHBhdGggZD0iTTI2LjIsODguMmMzLjMsMiw2LjcsMy42LDEwLjIsNC43Yy0zLjUtNi4yLTYuMy0xMi42LTguOC0xOC41Yy0zLjEtNy4yLTUuOC0xMy41LTktMTcuMmMtMS45LDgtMiwxNi40LTAuMywyNC43ICAgQzIwLjYsODQuMiwyMy4yLDg2LjMsMjYuMiw4OC4yeiIvPgoJPHBhdGggZD0iTTMwLjksNzNjMi45LDYuOCw2LjEsMTQuNCwxMC41LDIxLjJjMTUuNiwzLDMyLTIuMyw0Mi42LTE0LjZDNjcuNyw3Niw1Mi4yLDY5LjYsMzcuOSw2MC43QzMyLDU3LDI2LjUsNTMsMjEuMyw0OC42ICAgYy0wLjYsMS41LTEuMiwzLTEuNyw0LjZDMjQuMSw1Ny4xLDI3LjMsNjQuNSwzMC45LDczeiIvPgo8L2c+Cjwvc3ZnPg==

And that pattern will not be processed appropriately by the code you are using because of the + sign:

const base64EncodedImageString = image.replace(
      /^data:image\/\w+;base64,/,
      ""
    );

Please, see how the result actually contains the data:image/svg+xml;base64, information as prefix:

image processing

In order to successfully handle the SVG use case, you could modify the regular expression to this:

const base64EncodedImageString = image.replace(
      /^data:image\/(\w|\+)+;base64,/,
      ""
    );

Please, note how now the base64 is successfully extracted:

image processing with modified regex

If the content type is not set like image/svg+xml, please, consider change it to that value, it could be of help as well.

Related