Облачная функция, генерирующая миниатюры, не перезаписывает старые миниатюры с тем же именем - PullRequest
0 голосов
/ 19 сентября 2018

Я использую облачные функции для изменения размера и создания миниатюр для загруженных изображений в Firebase Storage.При первой загрузке создаются эскизы, но я также хочу иметь возможность редактировать эти изображения, сохраняя то же имя.Вот как я это делаю:

Я загружаю изображение с этой функцией на клиент:

    uploadImage (imageFile, folderName, imageName){
         const storageRef = firebase.storage().ref();
         // need to prefix image name with "slot_"
         storageRef.child(`${folderName}/slot_${imageName}`).put(imageFile)
    }

Затем с помощью этой облачной функции создаются эскизы:

export const generateThumbs = functions.storage.object().onFinalize(async 
    object => {
const bucket = gcs.bucket(object.bucket)
const filePath = object.name;
const fileName = filePath.split('/').pop();
const bucketDir = dirname(filePath);
const slotSizes = [64,250]

const temporaryDirectory = join(tmpdir(), `thumbs_${fileName}`);
const temporaryFilePath = join(temporaryDirectory, 'source.png');

// avoid loop includes only images
if (fileName.includes('thumb_') ||
    !object.contentType.includes('image')) {
    return false;
}

await fileSystem.ensureDir(temporaryDirectory);

// original file in temp directory
await bucket.file(filePath).download({
    destination: temporaryFilePath
});
const slotUploadPromises = slotSizes.map(async size => {
        const thumbName = `thumb_${size}_${fileName}`;
        const thumbPath = join(temporaryDirectory, thumbName);

        await sharp(temporaryFilePath).resize(size, size).toFile(thumbPath);

        return bucket.upload(thumbPath, {
            destination: join(bucketDir, thumbName),
            metadata: {
                contentType: 'image/jpeg',
            }
        })
    });


await Promise.all(slotUploadPromises)
// removes temp directory
return fileSystem.remove(temporaryDirectory);

Так что, если я позвоню uploadImage(appleImage, 'MyImages', 'test'), у меня в папке хранения будет 3 изображения (имя очень важно):

  • slot_test
  • thumb_250_slot_test
  • thumb_64_slot_test

В этот момент, если я позвоню снова uploadImage(avocadoImage, 'MyImages', 'test'), я ожидаю, что в хранилище будет та же "структура именования", но с обновленным изображением вместо старых, поэтому новые эскизыследует просто перезаписать старые.Что на самом деле происходит, так это то, что «базовое» изображение обновляется, а оба эскиза - нет.Окончание:

  • slot_test ( отображение ОБНОВЛЕНО изображение )
  • thumb_250_slot_test ( отображение миниатюры OLD image )
  • thumb_64_slot_test ( отображение миниатюры OLD изображения )

I'mЗарегистрированы функции облака, ошибки не генерируются во время выполнения функции, миниатюры создаются нормально, и консоль Firebase также обновляет дату создания миниатюр, но я все еще получаю старое изображение миниатюр.Я попытался удалить временный каталог, используя fs-extra emptyDir(), я пытался сначала удалить все миниатюры (через клиента), а затем снова загрузить безуспешно.

РЕДАКТИРОВАТЬ: нашел решение моей проблемы с помощью НЕ создания любой временной папки или временных файлов и использования взамен острого конвейера.Тем не менее, я все еще пропускаю основную проблему в коде выше.Я совершенно уверен, что по какой-то причине эта функция не удаляла временную папку, и это создавало проблемы всякий раз, когда я пытался перезаписать изображения.Эта функция работает:

export const generateThumbs = functions.storage.object().onFinalize(async object => {
const bucket = gcs.bucket(object.bucket)
const filePath = object.name;
const fileName = filePath.split('/').pop();
const bucketDir = dirname(filePath);

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

if (fileName.includes('thumb_') || !object.contentType.includes('image')) {
    return false;
}

if (fileName.includes('slot')) {
    // array of promises
    const slotUploadPromises = slotSizes.map(async size => {
        const thumbName = `thumb_${size}_${fileName}`;
        const thumbPath = join(path.dirname(filePath), thumbName);
        const thumbnailUploadStream = bucket.file(thumbPath).createWriteStream({ metadata });

        const pipeline = sharp();

        pipeline.resize(size, Math.floor((size * 9) / 16)).max()
            .pipe(thumbnailUploadStream);

        bucket.file(filePath).createReadStream().pipe(pipeline);

        return new Promise((resolve, reject) => 
               thumbnailUploadStream
               .on('finish', resolve)
               .on('error', reject));
    });
    await Promise.all(slotUploadPromises)
}
...