在Firebase函数中使用Imagemagick时,请使用-auto-orient。

3
我按照Firecasts的Firebase函数教程(https://www.youtube.com/watch?v=pDLpEn3PbmE&t=338s)使用Firebase上传图片并创建缩略图,一切都很顺利。但是,当我上传用iPhone拍摄的照片时,它会被旋转(竖直照片保存为水平照片)。因此,我进行了一些研究,并发现了ImageMagick的-auto-orient参数(http://magick.imagemagick.org/script/command-line-options.php#auto-orient)。但是,我不确定如何将此参数添加到spawn函数中以考虑此参数。以下是我的工作代码(仅涉及相关部分),不包括-auto-orient
...
return bucket.file(filePath).download({
        destination: tempFilePath
    })
    .then(() => {
        console.log('Image downloaded locally to', tempFilePath);
        return spawn('convert', [tempFilePath, '-thumbnail', '200x200>', tempFilePath]);
    })
    .then(() => {
        console.log('Thumbnail created!');
        const thumbFilePath = filePath.replace(/(\/)?([^\/]*)$/, '$1thumb_$2');
        console.log(`thumbFilePath: ${thumbFilePath}`);
        return bucket.upload(tempFilePath, {
            destination: thumbFilePath
        });
    }) 
...

我尝试使用-auto-orient参数的代码

...
return bucket.file(filePath).download({
        destination: tempFilePath
    })
    .then(() => {
        console.log('Image downloaded locally to', tempFilePath);
        return spawn('convert', ['-auto-orient', tempFilePath, '-thumbnail', '200x200>', tempFilePath]);
    })
    .then(() => {
        console.log('Thumbnail created!');
        const thumbFilePath = filePath.replace(/(\/)?([^\/]*)$/, '$1thumb_$2');
        console.log(`thumbFilePath: ${thumbFilePath}`);
        return bucket.upload(tempFilePath, {
            destination: thumbFilePath
        });
    })
...

但是当我把它部署到Firebase上并尝试上传图片时,我收到了以下错误消息,它没有给我关于为什么不起作用的很多信息:
“函数执行花费了6227毫秒,完成状态为:'连接错误'”
有任何想法吗?

你解决过这个问题吗?我也遇到了同样的错误。 - Lee Salminen
不,我还没有时间调查这个问题。 - koala
昨晚我成功解决了这个问题。当你有时间调查时,请查看我的答案! - Lee Salminen
2个回答

1

我也遇到了GCF内部的“连接错误”消息。我做了三件事来解决它,但我不确定是其中一个原因还是全部三个原因。它们是:

  • 未解决的Promise
  • 没有使用GCF提供的callback()函数
  • 使用require('child-process-promise').exec而不是require('child-process-promise').spawn

下面是我的代码,它已经连续运行了12小时,每秒运行2次,没有遇到“连接错误”消息。

const Storage = require('@google-cloud/storage');
const exec    = require('child-process-promise').exec;
const uuidv1  = require('uuid/v1');
const _       = require('lodash');

exports.processFile = (event, callback) => {
    const file         = event.data;

    if(file.contentType.indexOf('image/') !== 0) {
        console.log(file.name + ' is not an image');
        callback();
    } else if(!_.isUndefined(file.metadata) && !_.isUndefined(file.metadata['x-processed'])) {
        console.log(file.name + ' was already processed');
        callback();
    } else if(file.resourceState === 'not_exists') {
        console.log('This is a deletion event.');
        callback();
    } else if (file.resourceState === 'exists' && file.metageneration > 1) {
        console.log('This is a metadata change event.');
        callback();
    } else {
        const storage       = new Storage();
        const bucket        = storage.bucket(file.bucket);
        const parts         = file.name.split('.');
        const tempFilePath  = '/tmp/' + uuidv1() + '.' + _.last(parts);
        const tempFinalPath = '/tmp/' + uuidv1() + '.' + _.last(parts);

        console.log('Processing file: ' + file.name);

        return bucket.file(file.name).download({
            destination: tempFilePath
        })
        .then(() => {
            console.log('Image downloaded locally to ', tempFilePath);

            return exec(`convert -auto-orient "${tempFilePath}" "${tempFinalPath}"`)
        })
        .then(() => {
            console.log('uploading modified file to ' + file.name);

            return bucket.upload(tempFinalPath, {
                destination: file.name,
                contentType: file.contentType,
                metadata: {
                    metadata: {
                        "x-processed": "yes"
                    }
                }
            })
        })
        .then(() => {
            console.log('file uploaded successfully to ' + file.name);
            callback()
        })
        .catch((err) => {
            callback(err);
        })
    }
}

0

正确排列参数的顺序非常重要。

 await spawn("convert", [src, "-auto-orient", "-thumbnail",  "200x200>", `${dir}/thumb_001_${name}${ext}`]);

"-thumbnail" 但没有 "-auto-orient" 会起作用,反之则不会。

参见 imagemagick 文档

此操作符读取并重置 EXIF 图像配置文件设置的“方向”,然后执行适当的90度旋转,以定向图像,以便正确查看。

这类似于 -resize,但它针对速度进行了优化,并且除颜色配置文件外,删除任何图像配置文件以减小缩略图大小。要同时去掉颜色配置文件,请在此选项之前或之后添加 -strip。

问题是先运行了 -thumbnail,剥离了所有的方向信息,然后当 -auto-orient 在没有方向设置的情况下运行并设置 EONNT 错误时,就会出现问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接