Azure BlobTrigger对每个新Blob触发> 5次

时间:2019-11-16 11:08:44

标签: azure azure-functions azure-storage-blobs

以下触发器在将blob(图像)上的exif数据上传到Azure存储后,将其删除。问题在于,每个Blob触发器都会触发至少5次。

在触发器中,通过向其中写入新的数据流来更新blob。我以为blob receipts会阻止对该Blob进一步触发Blob触发器。

[FunctionName("ExifDataPurge")]
public async System.Threading.Tasks.Task RunAsync(
    [BlobTrigger("container/{name}.{extension}", Connection = "")]CloudBlockBlob image,
    string name,
    string extension,
    string blobTrigger,
    ILogger log)
{
    log.LogInformation($"C# Blob trigger function Processed blob\n Name:{name}");

    try
    {
        var memoryStream = new MemoryStream();
        await image.DownloadToStreamAsync(memoryStream);
        memoryStream.Position = 0;
        using (Image largeImage = Image.Load(memoryStream))
        {
            if (largeImage.Metadata.ExifProfile != null)
            {
                //strip the exif data from the image. 
                for (int i = 0; i < largeImage.Metadata.ExifProfile.Values.Count; i++)
                {
                    largeImage.Metadata.ExifProfile.RemoveValue(largeImage.Metadata.ExifProfile.Values[i].Tag);
                }

                var exifStrippedImage = new MemoryStream();
                largeImage.Save(exifStrippedImage, new SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder());
                exifStrippedImage.Position = 0;

                await image.UploadFromStreamAsync(exifStrippedImage);
            }
        }
    }
    catch (UnknownImageFormatException unknownImageFormatException)
    {
        log.LogInformation($"Blob is not a valid Image : {name}.{extension}");
    }
}

3 个答案:

答案 0 :(得分:2)

触发器的处理方式是通过将收据存储在容器 azure-webjobs-hosts 中来跟踪已处理了哪些Blob。任何没有收据的Blob或旧的收据(基于Blob ETag)将被处理(或重新处理)。

由于您正在呼叫 await image.UploadFromStreamAsync(exifStrippedImage); ,因此它会被触发(假设尚未处理)

答案 1 :(得分:2)

调用await image.UploadFromStreamAsync(exifStrippedImage);时,它将更新blob,以便blob函数将再次触发。

您可以尝试检查Blob上现有的CacheControl属性,如果它已被更新以打破循环,则不对其进行更新。

// Set the CacheControl property to expire in 1 hour (3600 seconds)
blob.Properties.CacheControl = "max-age=3600";

答案 2 :(得分:0)

因此,我通过在状态处理过程中将状态存储在元数据中来解决此问题。

https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-container-properties-metadata

然后,触发器包含用于检查元数据的防护。

if (image.Metadata.ContainsKey("Status") && image.Metadata["Status"] == "Processed")
{
    //an subsequent processing for the blob will enter this block. 
    log.LogInformation($"blob: {name} has already been processed");
}
else
{
     //first time triggered for this blob
     image.Metadata.Add("Status", "Processed");
     await image.SetMetadataAsync();
}

其他答案为我指明了正确的方向。我认为使用元数据更为正确。当我们可以存储元数据时,将ETag存储在其他地方似乎是多余的。 “ CacheControl”的使用似乎太过分了,其他开发人员可能对我做了什么以及为什么这样做感到困惑。