blob to file conversion returning application/octet-stream other than File in javascript

I am uploadinig images from input fields to firebase storage after compressing the image using canvas. but after uploading the file to the firebase it is in the format application/octet-stream

before i added this compress function, everything went well

my compress function which I copied from here (also done some minor editing):

function compressImg(file) {
    const MAX_WIDTH = 768;
    const MAX_HEIGHT = 1024;
    const MIME_TYPE = "image/jpeg";
    const QUALITY = 0.7;

    var output;
    const blobURL = URL.createObjectURL(file);
    const img = new Image();
    img.src = blobURL;
    img.onerror = function() {
        URL.revokeObjectURL(this.src);
        toastr["error"]("Cannot load image", "Error");
        console.log("Cannot load image");
    };
    img.onload = function() {
        URL.revokeObjectURL(this.src);
        const [newWidth, newHeight] = calculateSize(img, MAX_WIDTH, MAX_HEIGHT);
        const canvas = document.createElement("canvas");
        canvas.width = newWidth;
        canvas.height = newHeight;
        const ctx = canvas.getContext("2d");
        ctx.drawImage(img, 0, 0, newWidth, newHeight);

        canvas.toBlob(
            (blob) => {
                theBlob = blob;
                theBlob.lastModifiedDate = new Date();
                theBlob.name = 'tempName.jpeg';
                output = theBlob;

            },
            MIME_TYPE,
            QUALITY
        );
    };
    return output;
}

function calculateSize(img, maxWidth, maxHeight) {
    let width = img.width;
    let height = img.height;

    // calculate the width and height, constraining the proportions
    if (width > height) {
        if (width > maxWidth) {
            height = Math.round((height * maxWidth) / width);
            width = maxWidth;
        }
    } else {
        if (height > maxHeight) {
            width = Math.round((width * maxHeight) / height);
            height = maxHeight;
        }
    }
    return [width, height];
}

this is how I am uploading to firebase

 var compressedImg = compressImg(imageList[i]);
 await ref.put(compressedImg);

Answer

The documentation says,

If no contentType metadata is specified and the file doesn’t have a file extension, Cloud Storage defaults to the type application/octet-stream

Try adding metadata as shown below:

const metadata = {
  contentType: 'image/jpeg',
};

await ref.put(compressedImg, metadata);

Make sure you replace content-type with your file’s mime-type.


The other problem is your compressImg function seems to be returning undefined. Try refactoring your code to this:

async function compressImg(file) {
  // Resolve the promise when you get compressed image blog
  return new Promise((resolve, reject) => {
    console.log("Compressing image");
    const MAX_WIDTH = 768;
    const MAX_HEIGHT = 1024;
    const MIME_TYPE = "image/jpeg";
    const QUALITY = 0.7;

    const blobURL = URL.createObjectURL(file);
    const img = new Image();
    
    img.src = blobURL;
    img.onerror = function () {
      URL.revokeObjectURL(this.src);
      toastr["error"]("Cannot load image", "Error");
      console.log("Cannot load image");
    };

    img.onload = function () {
      URL.revokeObjectURL(this.src);
      const [newWidth, newHeight] = calculateSize(img, MAX_WIDTH, MAX_HEIGHT);
      const canvas = document.createElement("canvas");
      canvas.width = newWidth;
      canvas.height = newHeight;
      const ctx = canvas.getContext("2d");
      ctx.drawImage(img, 0, 0, newWidth, newHeight);
      canvas.toBlob(
        (blob) => {
          console.log("Blob");
          theBlob = blob;
          theBlob.lastModifiedDate = new Date();
          theBlob.name = 'tempName.jpeg';
          console.log("returning output");
          return resolve(theBlob); // <-- resolving promise
      },
      MIME_TYPE,
      QUALITY
    );
  };
})

Then call your function before upload to Firebase storage:

const file = document.getElementById("input-field-ID").files[0];
const compressedImage = await compressImg(file);
// await the promise    ^^^^^

const metadata = {
  contentType: 'image/jpeg',
};

await ref.put(compressedImg, metadata);