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);
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);