node.js загружает вывод imagemagick в AWS S3

У меня проблема с манипулированием изображением с помощью imagemagick, а затем загрузить его на S3. Полученный объект имеет другой (больший) размер и кажется поврежденным. Если я сделаю промежуточный шаг и сначала сохраню вывод в локальном tmp-файле и прочту его обратно, то загрузлю результат, все выглядит нормально. Это код, который НЕ работает.

im.resize({
    srcData: imageObject.Body,
    width: variant.width,
    height: variant.height,
    customArgs: ['-auto-orient']
}, function(err, stdout, stderr) {
    if (err) {
        // This resize completed successfully
        log.err('Failed calling imageMagick, bail out', err);
        callback(err);
        return;
    }

    var fileName = cfg.aws.s3.uploadDir +
                    photo.imageId + '/' +
                    variant.width + 'x' + variant.height + '.jpg';
    log.info('Storing image at S3 ' + fileName);
    //fs.writeFileSync('/tmp/xxx.jpg', stdout, 'binary');
    //stdout = fs.readFileSync('/tmp/xxx.jpg');
    var x = new Buffer(stdout);
    console.log(x);
    s3.putObject(
        {
            Bucket: cfg.aws.s3.bucket,
            Key: fileName,
            Body: x,
            ContentType: 'image/jpeg',
            ACL: 'public-read'
        },
        function(err, data) {
            if (err) {
                // Failed saving to S3
                log.error('Failed saving to S3', err);
            }

            callback(err);
        }
    );
});

Раскомментируйте fileWriteSync и fileReadSync, и он работает правильно.

Вывод команды console.log(x) в двух случаях: BAD:

Буфер c3 bf c3 98 c3 bf c3 a0 00 10 4a 46 49 46 00 01 01 01 00 01 00 01 00 00 c3 bf c3 9b 00 43 00 06 04 05 06 05 04 06 06 05 06 07 07 06 08 0a 10 0a 0a 09 09 ...>

ХОРОШО:

Буфер ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 01 00 01 00 00 ff db 00 43 00 06 04 05 06 05 04 06 06 05 06 07 07 06 08 0a 10 0a 0a 09 09 0a 14 0e 0f 0c 10 ...>

как вы можете видеть, хороший - это правильный jpeg, плохой, хотя и содержит похожие последовательности, такие как 4a 46 49 46 = JFIF, однако некоторые байты выключены, и есть сдвиги, весь файл больше примерно на 20% в плохом случае,

Что-то делать с кодировкой? Я пробовал несколько вещей, но я потерян в этот момент.

Спасибо!

Обновление № 1: Очевидно, это связано с кодировкой UTF, но я до сих пор не до конца понимаю, что происходит в этом случае. По-видимому, c3 bf c3 98 c3 bf c3 a0 00 10 4a 46 49 46 00 01 - это кодировка UTF:

U+00FF LATIN SMALL LETTER Y WITH DIAERESIS character (ÿ)
U+00D8 LATIN CAPITAL LETTER O WITH STROKE character (Ø)
U+00FF LATIN SMALL LETTER Y WITH DIAERESIS character (ÿ)
U+00E0 LATIN SMALL LETTER A WITH GRAVE character (à)
U+0000 <control> character
U+0010 <control> character
U+004A LATIN CAPITAL LETTER J character
U+0046 LATIN CAPITAL LETTER F character
U+0049 LATIN CAPITAL LETTER I character
U+0046 LATIN CAPITAL LETTER F character
U+0000 <control> character
U+0001 <control> character

когда FF D8 FF .. это именно то, что я ожидал.

Я знаю, как заставить код работать без временных файлов (заменить var x = new Buffer (stdout); на var x = new Buffer (stdout, 'binary'))

Однако я все еще не могу сказать, что я полностью понимаю, что здесь произошло, это должно быть без обертки Buffer(), у какого компонента есть проблема? ImageMagick? Буфер?

2 ответа

Это, очевидно, очень поздно, однако я сам столкнулся с этим вопросом, вот как я получил это работает;

ImageMagick.resize(params, function(err, stdout, stderr) {
    // Handle errors

    // Save the output of imagemagick to S3
    S3.putObject({
        Bucket: bucketName,
        Key: fileName,
        Body:  new Buffer(stdout, "binary")
    }).promise().then(function(data){
      // Success
    }).catch(function(err){
      // Error
    });
});

Ключевой частью этого является, очевидно,; new Buffer(stdout, "binary"), Если вы не знаете, будет ли ответ буфером или нет, вы можете использовать Buffer.isBuffer метод и сделать следующее;

var body = ( Buffer.isBuffer(stdout) ? stdout : new Buffer(stdout, "binary") );

Не уверен, что ОП решил проблему, но у меня тоже была похожая проблема, когда изображения, загруженные на S3, были больше, чем исходные файлы. Не могли бы вы сказать мне, что содержит стандартный вывод (то есть, это поток необработанных байтов?)

Я решил проблему, установив параметр Body: для использования буфера в кодировке base64 вместо двоичного буфера. Я не совсем уверен, почему это решило проблему, но я подозреваю, что это как-то связано с этим:

Схемы кодирования Base64 обычно используются, когда необходимо кодировать двоичные данные, которые должны храниться и передаваться через носитель, предназначенный для работы с текстовыми данными. Это необходимо для того, чтобы данные оставались без изменений во время транспортировки.

источник: MDN

Другие вопросы по тегам