Downloading file from Azure Blob container using call template

I have a few question regarding downloading a file from Azure Blob container using a call template:

  1. Is there a place to configure a SAS token for authorization without the need to configure this token as request parameters in every separate call?

  2. How to configure, that the result of a Get call, is the file content itself? Without a JSON or XML wrapper body. This call is more similar in principle to an FTP or HTTP download call

Thanks in advance for any suggestions!

Hey Peter,

Thank you for your question!
I hope that the answers below will nudge you in the right direction.

1. Setting a SAS token

Let’s take this example of an Azure blob storage URL with a SAS token:

https://storageaccountname.blob.core.windows.net/sascontainer/sasblob.txt?sv=2019-02-02&st=2019-04-29T22%3A18%3A26Z&se=2019-04-30T02%3A23%3A26Z&sr=b&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https&sig=koLniLcK0tMLuMfYeuSQwB%2BBLnWibhPqnrINxaIRbvU%3D

As you probably already know, you can use path variables to extend the base URL of your call.
I understand that setting all query parameters (sv, st, se …) of the SAS token via the “parameters” list can be tedious, especially for testing/debugging.
Therefore, I recommend attaching the SAS token to the URL just before the call is being executed by using call template processes.

  1. Make sure that a process action definition called “Add/Edit record” exists in your application under all settings > process action definitions. It should look like this.

  2. Add a call template process to your call template. Choose these settings

  3. Set the call template process parameter with the description “record” to the “expression” “this”.

  4. Set the call template process parameter with the description “values” to the “expression” something like this:

[< “url”, url:load( this.url.tostring().concat(“?SASToken”) ) >]

Beware that you use the correct double quotes when you copy and paste the expression above. The expression should look like this when formatted:

  1. Now execute a test call with the test panel without defining any parameters for the SAS token. The call will have the SAS token attached

Feel free to experiment with step 4 to make your token more dynamic. I defined it as a simple string, but you can split it up in and set the dynamic parts of the token with a more advanced Novulo expression.
Also, instead of simply editing the URL of the current call with an add/edit process action definition, you can also define your own custom process. Something like “N_Call - Set SAS token”. It would take the current call as an input and then execute your custom steps to come up with the right token and finally attach it to the URL.

2. Extract a file from the XML/JSON body of a response

I would also recommend using a call template process. First, build a custom process to extract a file from an N_Response record, like explained below. Then, set that process as a call template process with the trigger “After processing”.
With each call, your custom process will then be executed to generate a file which you can save where you want.

Building the custom process

  1. Add a new process to a (new?) component called “N_Response - Convert azure blob body into file” or something similar. It should take at least a “N_Response” record as an input.
  2. Within that process, you will probably have to use several plugin actions to convert the raw body string (JSON/XML) of the trigger.response into a “Novulo datatype object”. The serialization plugin can help you with that.
  3. Once you have converted it, you can extract the node that contains the actual file string. Use the TupleExtLookup action of the tuple extensions plugin to choose the right node/tuple.
  4. Then you can convert the file-string into an actual file of any type by using the “FileFromStringAction” of the File Extensions plug-in. If the string is base64 encoded, you can also use “FileFromBase64Action”.
  5. Now you have a file, and you can do whatever you want with it. Link it to the trigger.response record, save it to a special folder, or set it as a product media.

Hint: Take a look at M7899 and the process “N_Response - Execute sequential JSON import”. Here, you can see examples of the plugin actions that I mentioned earlier. Hopefully this will help you with selecting and setting the right plugin actions.

Let me know if you have any further questions or if I missed something.

Regards
Joachim

Thank you Joachim for the quick and detailled answer! I’ll have a try with all the suggestions.

Just to check: In the first step, when the url is altered with the call template process. Is it then still possible to add additional path variables / query parameters to the call template? I.e. for other Blob Rest API call like:

https://myaccount.blob.core.windows.net/mycontainer?restype=container&comp=list

in other words, will the system recognize it has to put a ‘&’ instead of a ‘?’ after the altered base url that includes the SAS token?

https://myaccount.blob.core.windows.net/mycontainer?<SASToken>&restype=container&comp=list

Hey Peter,

Since we are altering the URL with the “After build” trigger, the URL has already been build based on the “server” field at the call template and your custom parameters.
So the URL looks like this before we start attaching the SAS token:

https://myaccount.blob.core.windows.net/mycontainer?restype=container&comp=list

I suggest that you replace the ‘?’ with an ‘&’ when you follow step 1.4 of the instructions above.

[< “url”, url:load( this.url.tostring().concat(“ & SASToken”) ) >]

The final URL will look like this:

https://myaccount.blob.core.windows.net/mycontainer?restype=container&comp=list&<SASToken>

You can also include an expression to either choose a ‘?’ or a ‘&’ depending on the current situation:

string:if(this.url.contains(?), “&”, “?”)

So when the URL already contains any query parameters and therefore also a ‘?’, the SAS token will be attached with a ‘&’ sign. Otherwise, a ‘?’ will be used.

This would be the complete expression:

[< “url”, url:load( this.url.tostring().concat(string:if(this.url.contains(?), “&”, “?”)).concat(“SASToken”) ) >]

1 Like

Hey Peter,

Your question triggered me to extend component M10074.
With revision 103 it should be possible to download files with GET calls like yours. Without having to build a custom process like I described in step 2 above with complicated plugin actions, files are stored automatically at the response.
I haven’t tested my changes yet, but I wanted to let you know that it is in the making. I will test it shortly.
Feel free to also deploy and test revision 103. If you find any bugs, let me know.

Thank you for your proactive help and thoughts! Once I have the first step working, I will start testing on your update. That saves a lot of work :+1:

It seems to work :slight_smile:
With this configuration, I was able to download an image.


The actual file is stored at the response and has the name that has been defined with the file name expression.
image

Make sure to add a custom web.config setting for novulofileextensions.getfromurl.allowedhosts before installing M10074 r103. Also see “Allowed media hosts”
For my test I used “images.unsplash.com” but yours will be different. Define multiple hosts and separate them with a semicolon and no spaces.
image

Great to hear, thanks for the detailled solution :+1: