4

I would like to process an input file and output it to some location for ex. FTP or Azure storage. I am trying to use Azure Function with SaasFile input/output. I am getting below error:

2016-07-14T00:44:53 Welcome, you are now connected to log-streaming service. 2016-07-14T00:45:00.580 Script for function 'HttpTriggerCSharp1' changed. Reloading. 2016-07-14T00:45:00.580 Compiling function script. 2016-07-14T00:45:00.721 run.csx(24,25): error CS0622: Can only use array initializer expressions to assign to array types. Try using a new expression instead. 2016-07-14T00:45:00.721 Compilation failed.

Here is my function signature:

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, string output, TraceWriter log)

Bindings:

{
  "bindings": [
    {
      "authLevel": "function",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in"
    },
    {
      "name": "res",
      "type": "http",
      "direction": "out"
    },
    {
      "type": "apiHubFile",
      "name": "output",
      "path": "path/{file}",
      "connection": "ftp_FTP",
      "direction": "out"
    }
  ],
  "disabled": false
}

I think I am missing something in Run signature. I couldn't find it on Azure documentation.

I need help figure out how to process using FTP and Azure Storage. Thanks for your help.

Janusz Nowak
  • 2,595
  • 1
  • 17
  • 36
Manish Jain
  • 9,569
  • 5
  • 39
  • 44
  • The error indicates an invalid use of an array initializer expression in the method body (line 24). Do you mind sharing that? – Fabio Cavalcante Jul 14 '16 at 04:05
  • @FabioCavalcante - Line 24 - const string path = {output}; – Manish Jain Jul 14 '16 at 05:13
  • That is exactly the line that is failing, as this is not valid syntax. What are you trying to accomplish? – Fabio Cavalcante Jul 14 '16 at 05:36
  • @FabioCavalcante - I am trying to get FTP path variable and save a file to that location using SaasFile. I have created output FTP endpoint on integrate tab as you can see above in bindings json. I can't find exact syntax in Azure docs. Let me know if you need high level overview or more info. Thanks! – Manish Jain Jul 14 '16 at 06:15
  • I was able to process a blob but not a file. Is Azure storage file supported? – Manish Jain Jul 14 '16 at 20:56

4 Answers4

3

If you have to use a Http trigger and need to create the file name in the function itself based on some header values or what not, you use use this sample:

Please make sure, you are using Functions version 0.4 or higher for this (it is being released today)

#r "Microsoft.Azure.WebJobs.Extensions.ApiHub"

using System.Net;
using Microsoft.Azure.WebJobs;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log, IBinder binder)
{
    //Get request  body  
    string data = await req.Content.ReadAsStringAsync();

    string fileName = "path/" + Guid.NewGuid().ToString() + ".txt";

    var writer = binder.Bind<TextWriter>(new ApiHubFileAttribute("DROPBOX_dropbox", fileName, FileAccess.Write));

    writer.Write(data);
    return req.CreateResponse(HttpStatusCode.OK);  
}

bindings:

{
  "bindings": [
    {
      "authLevel": "function",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in"
    },
    {
      "name": "res",
      "type": "http",
      "direction": "out"
    }
  ],
  "disabled": false
}
Matt
  • 74,352
  • 26
  • 153
  • 180
1

Here is one way you can do it, assuming you output to a specific file name. I am binding to a dropbox file in this example.

using System.Net;

public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log, out string output)
{
    output = req.Content.ReadAsStringAsync().GetAwaiter().GetResult();

    return req.CreateResponse(HttpStatusCode.OK);   
}

bindings:
{
  "bindings": [
    {
      "authLevel": "function",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in"
    },
    {
      "type": "http",
      "name": "res",
      "direction": "out"
    },
    {
      "type": "apiHubFile",
      "name": "output",
      "path": "path/b.txt",
      "connection": "dropbox_DROPBOX",
      "direction": "out",
    }
  ],
  "disabled": false
}

In order to bind to different file names, you will need to have an input or input trigger and pass the file name to output. same as all other samples.

0

You don't really need a http trigger for this. Here is an example which watches a folder(input-cs) for new files in dropbox and copies the file to a folder (output-cs) in googledrive:

using System;

public static void Run(string input, out string output, TraceWriter log)
{
    output = input;
}

bindings:

{

 "bindings": [
    {
      "type": "apiHubFileTrigger",
      "name": "input",
      "direction": "in",
      "path": "input-cs/{name}",
      "connection": "dropbox_DROPBOX"
    },
    {
      "type": "apiHubFile",
      "name": "output",
      "direction": "out",
      "path": "output-cs/{name}",
      "connection": "googledrive_GOOGLEDRIVE"
    }
  ],
  "disabled": false
}
Matt
  • 74,352
  • 26
  • 153
  • 180
  • Can you show one example with Azure storage file, SQL DB table and FTP ? Any idea when it will be supported? – Manish Jain Jul 20 '16 at 21:27
  • What do you exactly need the sample to do? These are all currently supported except the Azure files. Azure Blobs, Queues and Tables are fully supported as well as Dropbox, GoogleDrive, OneDrive,Ftp, Sftp, Box, Sql, SalesForce, ... – Henry Hamid Safi - MSFT Jul 21 '16 at 22:51
  • 1
    I have a need to create a function app, and I preferred Powershell but still preferred to try few experts sample. I wanted to listen to a dropbox folder and on file upload, move the file or changes to a existing file to FTP. Tried above , but I get Host Error: Microsoft.Azure.WebJobs.Extensions.ApiHub: Path 'input-cs' is invalid. IFolderItem.RootPath must be set to a valid directory location. Thinking that Dropbox wont allow root acces, I changed the input-cs path to input-cs/Apps/Azure/sitete/ but not able to run! :( Any help? – H Bala Jul 25 '16 at 11:54
  • Sorry, I was able to get this working by changing the "path" parameter in IN and OUT with "Docs/{name}" and {name} respectively. Not sure whether it is okay but now I get 200 Accepted on test run. Please suggest. – H Bala Jul 25 '16 at 12:57
  • But I get following error : 2016-07-25T12:52:07.957 Script for function 'SaasFileTriggerCSharp1' changed. Reloading. 2016-07-25T12:52:07.957 Compiling function script. 2016-07-25T12:52:08.020 Compilation succeeded. 2016-07-25T12:52:29.137 Exception while executing function: Functions.SaasFileTriggerCSharp1. Microsoft.Azure.WebJobs.Host: One or more errors occurred. Exception binding parameter 'input'. Microsoft.Azure.ApiHub.Sdk: /apim/dropbox/8b82684e13e44f499752a742adc4d30d/datasets/default/GetFileContentByPath?path=%7B%0A%20%20%20%20%22name%22:%20%22IMG-20140517-WA0001.jpg%22%0A%7D. – H Bala Jul 25 '16 at 13:30
  • Yes, the path should point to a valid path on your DropBox folder. the above sample is just an example. – Henry Hamid Safi - MSFT Jul 26 '16 at 16:48
0

Good news.. External File trigger is available for Azure functions.

If you want to process file in an external FTP folder, create a FTP connection first and then use it.

So your bindings array for FTP connection in function.json shown below.

{
  "bindings": [
    {
      "type": "apiHubFileTrigger",
      "name": "inputFile",
      "direction": "in",
      "path": "input-cs/{name}",
      "connection": "ftp_FTP"
    },
    {
      "type": "apiHubFile",
      "name": "$return",
      "direction": "out",
      "path": "output-cs/{name}",
      "connection": "ftp_FTP"
    }
  ],
  "disabled": false
}

In the above JSON,

path

Represents the path of the file to be processed. So in above case, azure function will be triggered when a file is added/modified in input-cs folder.

connection

Represents the External File connector name.

Malatesh Patil
  • 4,505
  • 1
  • 14
  • 14