Google Cloud Function 错误与 ChildProcessError

Google Cloud Function errors with ChildProcessError

这是我的云函数,每次上传图像时,它应该生成一个带水印的图像并将其存储在 firebase 存储中。

exports.generateWatermark = functions.storage
  .object()
  .onFinalize(async object => {
    try {
      const fileBucket = object.bucket; // The Storage bucket that contains the file.
      const filePath = object.name; // File path in the bucket.
      const contentType = object.contentType; // File content type.
      const metageneration = object.metageneration; // Number of times metadata has been generated. New objects have a value of 1.

      // Exit if this is triggered on a file that is not an image.
      if (!contentType.startsWith('image/')) {
        return console.log('This is not an image.');
      }

      // Get the file name.
      const fileName = path.basename(filePath);
      // Exit if the image is already a watermarked image.
      if (fileName.startsWith('watermark_')) {
        return console.log('Already a Watermarked image.');
      }

      if (!filePath.startsWith('pets')) {
        return console.log('Not a pet image: ', filePath);
      }

      // Download file from bucket.
      const bucket = admin.storage().bucket(fileBucket);
      const tempFilePath = path.join(os.tmpdir(), fileName);
      const tempWatermarkPath = path.join(os.tmpdir(), 'watermark.png');
      const metadata = {
        contentType: contentType,
      };

      // Generate a watermarked image using Jimp
      await bucket.file(filePath).download({destination: tempFilePath});
      await bucket
        .file('logo/cbs.png')
        .download({destination: tempWatermarkPath});
      console.log('Image downloaded locally to', tempFilePath, filePath);

      await spawn('convert', [
        tempFilePath,
        '-gravity',
        'NorthWest',
        '-draw',
        `"image Over 10,10,200,200 ${tempWatermarkPath}"`,
        tempFilePath,
      ]);
      console.log('Watermarked image created at', tempFilePath);

      // We add a 'watermark_' prefix
      const watermarkFileName = `watermark_${fileName}`;
      const watermarkFilePath = path.join(
        path.dirname(filePath),
        watermarkFileName,
      );
      // Uploading the watermarked image.
      await bucket.upload(tempFilePath, {
        destination: watermarkFilePath,
        metadata: metadata,
      });

      // Once the watermarked image has been uploaded delete the local file to free up disk space.
      fs.unlinkSync(tempFilePath);
      return fs.unlinkSync(tempWatermarkPath);
    } catch (err) {
      console.log('GENERATE WATERMARK ERROR: ', err);
      throw err;
    }
  });

代码中出现错误的部分是 imagemagick 部分:

  await spawn('convert', [
    tempFilePath,
    '-gravity',
    'NorthWest',
    '-draw',
    `"image Over 10,10,200,200 ${tempWatermarkPath}"`,
    tempFilePath,
  ]);

这是我遇到的错误:

有什么方法可以获得有关该错误的更多信息?错误甚至没有到达我的 catch 块..

childprocess.spawn 使用观察者模式。

调用 childprocess.spawn 得到的 return 值是一个 ChildProcess object,stdout 和 stderr 是 EventEmitters.

您需要一个额外的步骤来承诺现有接口,然后才能等待它。例如,

const spawn =  (command, args) => new Promise((resolve, reject) => {
  const cp = require('child_process').spawn(command, args);
  let err = null, out = null;
  cp.stdout.on('data', data => out += data.toString());
  cp.stdout.on('error', data => err += data.toString());
  cp.on('error', data => err += data.toString());
  cp.on('close', code =>  {
    (code === 0) ? resolve(out) : reject(err)
  });
})

childprocess.execFile 另一方面使用回调。这使得它可以轻松地使用 util.promisify 函数。例如

const util = require('util');

const execFile = util.promisify(require('child_process').execFile);


exports.generateWatermark = functions.storage
  .object()
  .onFinalize(async object => {
    try {
      //...

      await execFile('convert', [
        tempFilePath,
        '-gravity',
        'NorthWest',
        '-draw',
        `"image Over 10,10,200,200 ${tempWatermarkPath}"`,
        tempFilePath,
      ]);
     //...
   } catch (err) {
      console.log('GENERATE WATERMARK ERROR: ', err);
      throw err;
    }
  });