调整存储在 firebase 存储中的所有现有图像的大小,并通过 api 调用将新调整大小的图像 url 更新到数据库

Resize all existing images stored in firebase storage and update the newly resized image url to database via api call

我需要调整存储在 firebase 存储中的新图像和现有图像的大小。对于新图像,我启用了 firebase 的调整图像扩展。对于现有图像,如何调整图像大小并让新调整大小的图像 url 通过 api.

更新回数据库

这是我的 firebase 函数,用于从数据库中获取现有图像 urls。我的问题是如何调整图像大小并获取新图像url?

const functions = require("firebase-functions"); const axios =require("axios");

异步函数 getAlbums() {

const endpoint = "https://api.mydomain.com/graphql";
const headers = {
  "content-type": "application/json",
};

const graphqlQuery = {
  "query": `query Albums {
    albums {
      id
      album_cover
    }
  }`
};
functions.logger.info("Call API");
const response = await axios({
  url: endpoint,
  method: 'post',
  headers: headers,
  data: graphqlQuery
});

if(response.errors) {
    functions.logger.info("API ERROR : ", response.errors) // errors if any
} else {
    return response.data.data.albums;
}
}

exports.manualGenerateResizedImage = functions.https.onRequest(async () => {
    const albums = await getAlbums();
    functions.logger.info("No. of Album : ", albums.length);
});

我认为 Renaud Tarnec 的以下 answer 一定会对您有所帮助。

如果您查看 code of the "Resize Images" extension, you will see that the Cloud Function that underlies the extension is triggered by a onFinalize 事件,这意味着:

When a new object (or a new generation of an existing object) is successfully created in the bucket. This includes copying or rewriting an existing object.

因此,如果没有 rewriting/regenerating 现有图像,将不会触发扩展程序。

但是,您可以轻松编写自己的 Cloud Function,它执行相同的操作但会被触发,例如,通过调用特定的 URL (HTTPS cloud Function) or by creating a new document in a temporary Firestore Collection (background triggered CF)。

此 Cloud Function 将执行以下步骤:

  1. 获取你bucket的所有文件,见getFiles()方法 Google 云存储 Node.js 客户端 API。这个方法returns一个 GetFilesResponse object 这是一个文件实例数组。
  2. 通过遍历数组,对于每个文件,检查文件是否有 桶中相应调整大小的图像(取决于你的方式 配置了扩展,调整大小的图像可能在特定的 文件夹)
  3. 如果文件没有相应的调整大小的图像,执行 此文件的扩展云功能的业务逻辑相同。

有一个官方的 Cloud Function sample,它展示了如何创建一个 Cloud Storage 触发的 Firebase Function,它将根据上传的图像创建调整大小的缩略图并将它们上传到数据库 URL,(请参阅index.js 文件的最后几行)

注意:如果您有很多文件要处理,您很可能应该分批处理,因为 Cloud Function 的执行时间有 9 分钟的限制。此外,根据要处理的图像数量,您可能需要增加超时值 and/or 分配给 Cloud Function 的内存,请参阅 https://firebase.google.com/docs/functions/manage-functions#set_timeout_and_memory_allocation

以防有人需要。这就是我调整现有图片大小的方式。

const functions = require("firebase-functions");
const axios = require("axios");
const { Storage } = require("@google-cloud/storage");

const storage = new Storage();

// Don't forget to replace with your bucket name
const bucket = storage.bucket("projectid.appspot.com");

async function getAlbums() {
  const endpoint = "https://api.mydomain.com/graphql";
  const headers = {
    "content-type": "application/json",
  };

  const graphqlQuery = {
    query: `query Albums {
        albums {
          id
          album_cover
        }
      }`,
  };
  const response = await axios({
     url: endpoint,
     method: "post",
     headers: headers,
     data: graphqlQuery,
   });

  if (response.errors) {
    functions.logger.error("API ERROR : ", response.errors); // errors 
if any
  } else {
    return response.data.data.albums;
  }
}

function getFileName(url) {
  var decodeURI = decodeURIComponent(url);
  var index = decodeURI.lastIndexOf("/") + 1;
  var filenameWithParam = decodeURI.substr(index);
  index = filenameWithParam.lastIndexOf("?");
  var filename = filenameWithParam.substr(0, index);
  return filename;
}

function getFileNameFromFirestore(url) {
  var index = url.lastIndexOf("/") + 1;
  var filename = url.substr(index);
  return filename;
}

const triggerBucketEvent = async () => {
  bucket.getFiles(
    {
      prefix: "images/albums", // you can add a path prefix
      autoPaginate: false,
    },
    async (err, files) => {
      if (err) {
        functions.logger.error(err);
        return;
      }

      const albums = await getAlbums();

       await Promise.all(
        files.map((file) => {
          var fileName = getFileNameFromFirestore(file.name);

          var result = albums.find((obj) => {
             return getFileName(obj.album_cover) === fileName;
          });

      if (result) {
        var file_ext = fileName.substr(
          (Math.max(0, fileName.lastIndexOf(".")) || Infinity) + 1
        );
        var newFileName = result.id + "." + file_ext;
        // Copy each file on thumbs directory with the different name
        file.copy("images/albums/" + newFileName);

      } else {
        functions.logger.info(file.name, " not found in album list!");
      }
    })
  );
}
  );
};

exports.manualGenerateResizedImage = functions.https.onRequest(async () => {
  await triggerBucketEvent();
});