我正在使用云功能调整大小并生成Firebase存储中上传图像的缩略图。在第一次上传时,会生成缩略图,但我也希望能够在保留相同名称的情况下编辑这些图像。 这就是我的做法:
我将具有此功能的图像上传到客户端:
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张图像(命名很重要):
在这一点上,如果我再次调用uploadImage(avocadoImage, 'MyImages', 'test')
,我希望在存储中使用相同的“命名结构”,但使用更新的图像代替旧的图像,因此新的缩略图应仅覆盖旧的。实际发生的是“基本”图像被更新,而两个缩略图均未更新。结束于:
我已经广泛记录了云功能,在执行过程中未从该功能引发任何错误,正常创建了缩略图,并且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)
}