2
votes

I am trying to setup access to blob storage using a python function app but the file name is received from a post request not preset. The http trigger part works but i'm having trouble accessing files in my blob storage. This is my json:

{
"bindings": [
{
  "authLevel": "function",
  "type": "httpTrigger",
  "direction": "in",
  "name": "req",
  "methods": [
    "post",
    "get"
  ]
},
{
  "name": "inputblob",
  "type": "blob",
  "path": "sites/{httpTrigger}",
  "connection": "STORAGE",
  "direction": "in"
},
{
  "type": "http",
  "direction": "out",
  "name": "res"
}
],
"disabled": false
}

I saw an example (https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-storage-blob#input---configuration) using a queue trigger but when i do do something similar using http i get 'No value for named parameter 'httpTrigger''. My issue is that i don't know how to reflect a variable that is assigned in my python code in my path. When i do this container/{variable} i get a nullreference exception. This is my python code:

import os
import json
import sys
import logging
import azure.functions as func


_AZURE_FUNCTION_DEFAULT_METHOD = "GET"
_AZURE_FUNCTION_HTTP_INPUT_ENV_NAME = "req"
_AZURE_FUNCTION_HTTP_OUTPUT_ENV_NAME = "res"
_REQ_PREFIX = "REQ_"
def write_http_response(status, response):
    output = open(os.environ[_AZURE_FUNCTION_HTTP_OUTPUT_ENV_NAME], 'w')
    output.write(json.dumps(response))


env = os.environ
postreqdata = json.loads(open(env['req']).read())
print ('site: ' + postreqdata['site'])
site = postreqdata['site']+'.xlsx'
input_file = open(os.environ['inputBlob'], 'r')
clear_text = input_file.read()
input_file.close()
print("Content in the blob file: '{0}'".format(clear_text))

# Get HTTP METHOD
http_method = env['REQ_METHOD'] if 'REQ_METHOD' in env else 
_AZURE_FUNCTION_DEFAULT_METHOD
print("HTTP METHOD => {}".format(http_method))

# Get QUERY STRING
req_url = env['REQ_HEADERS_X-ORIGINAL-URL'] if 'REQ_HEADERS_X-ORIGINAL-URL' 
in env else ''
urlparts =req_url.split('?') 
query_string = urlparts[1] if len(urlparts) == 2 else ''
print("QUERY STRING => {}".format(query_string))

if http_method.lower() == 'post':
    request_body = open(env[_AZURE_FUNCTION_HTTP_INPUT_ENV_NAME], "r").read()
    print("REQUEST BODY => {}".format(request_body))

write_http_response(200, site)

note: i have made my connection string successfully ( i think) and i am new to azure and using the portal only

1

1 Answers

0
votes

This looks like an older version of function apps. In the new version, you can actually use the request handler to do all this work for you. I just started working in azure functions and if you want to access a file in blob storage, all you have to do is pass in the filename parameters in the form of http query, and use that query param name as the binding variable. Ex:

def main(req: func.HttpRequest, inputblob: func.InputStream):
   input_file_content = input_blob.read()

and in your binding you give

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    },
    {
      "type": "blob",
      "direction":"in",
      "name": "inputblob",
      "path": "upload/{filename}",
      "connection": "AzureWebJobsStorage"
    }
  ]
}

and you simply call the api with the query parameters filename

http://localhost:7071/api/HttpTriggerFileUpload?filename=file.ext

You can take a look at this