blob 到文件的转换返回 application/octet-stream 而不是 javascript 中的文件

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

我在使用 canvas 压缩图像后将输入字段中的图像上传到 firebase 存储。但将文件上传到 firebase 后,格式为 application/octet-stream

在我添加这个压缩功能之前,一切都很顺利

我从 here 复制的压缩函数(也做了一些小的编辑):

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];
}

这就是我上传到 firebase 的方式

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

documentation 说,

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

尝试添加如下所示的元数据:

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

await ref.put(compressedImg, metadata);

确保将内容类型替换为文件的 mime-type


另一个问题是您的 compressImg 函数似乎返回未定义。尝试将您的代码重构为:

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

然后在上传到 Firebase 存储之前调用您的函数:

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