3
votes

I'm using the latest Azure Function SDK in Visual Studio 2017, and I want to copy a blob from one container to another. The name stays the same, but the container name will be retrieved from the metadata of the source blob.

I started of with just trying to trigger the function and include the metadata as:

    [FunctionName("ScanFile")]
    public static void Run([BlobTrigger("tobescanned/{name}", Connection = "AzureWebJobsStorage")]Stream myBlob, IDictionary<string, string> metadata, string name, TraceWriter log)
    {
        log.Info($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
        log.Info($"metadata count {metadata.Count}");
    } 

This works, so then tried to do the copy as:

    [FunctionName("ScanFile")]
    public static void Run([BlobTrigger("tobescanned/{name}", Connection = "AzureWebJobsStorage")]Stream myBlob, IDictionary<string, string> metadata, string name,
        [Blob("employees/{name}", Connection = "AzureWebJobsStorage")]Stream outputBlob,
        TraceWriter log)
    {
        log.Info($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
        log.Info($"metadata count {metadata.Count}");

        myBlob.CopyTo(outputBlob);
    }

But now the function isn't event called, so have done something wrong with the bindings. Is there anything obvious I've done wrong? I've found it difficult finding examples using the new Function SDK.

The next step from this (when I've got it working) is to have the output container set at runtime. I thought it might be something like:

    [FunctionName("ScanFile")]
    public static void Run([BlobTrigger("tobescanned/{name}", Connection = "AzureWebJobsStorage")]Stream myBlob, IDictionary<string, string> metadata, string name,
        [Blob("{outputContainer}/{name}", Connection = "AzureWebJobsStorage")]Stream outputBlob, string outputContainer,
        TraceWriter log)
    {
        log.Info($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
        log.Info($"metadata count {metadata.Count}");

        outputContainer = metadata["Destination"];

        myBlob.CopyTo(outputBlob);
    }

Does this look like it would work (when I've got the output working)?

Thanks

1
Ex 2 - have a look at function.json when it's deployed to see which bindings it generated. Ex 3 won't work, you'd probably need to use ICollector.Mikhail Shilkov
@Mikhail The function.json only has the input binding, doesn't show the output so wasn't too sure what I had done wrongADringer

1 Answers

1
votes

Your second example worked fine on my side. Here is the function JSON generated in my function app. The direction is 'out' for blob binding.

{
  "bindings": [
    {
      "type": "blobTrigger",
      "path": "tobescanned/{name}",
      "direction": "in",
      "name": "myBlob"
    },
    {
      "type": "blob",
      "path": "employees/{name}",
      "direction": "out",
      "name": "outputBlob"
    }
  ],
  "disabled": false
}

Your third example can't work because the input parameter {outputContainer} must be given when the function is triggered. For your requirement, I suggest you use the Azure Storage Blob SDK to finish the copy action. Code below is for your reference.

[FunctionName("ScanFile")]
public static void Run([BlobTrigger("tobescanned/{name}")]CloudBlockBlob myBlob, string name,
    IDictionary<string, string> metadata)
{
    var destinationContainer = myBlob.Container.ServiceClient.GetContainerReference(metadata["Destination"]);
    destinationContainer.CreateIfNotExists();
    CloudBlockBlob outputBlob = destinationContainer.GetBlockBlobReference(name);
    outputBlob.StartCopy(myBlob);
}