Search code examples
azure-functionsazure-blob-storageazure-storageazure-storage-account

How to download a file into an Azure Storage account from a function app


I have just got started with Azure Function Apps. The following code should download a file with FTP from another server into an Azure storage account.

[FunctionName("UploadBlobFunction")]
public static async Task<IActionResult> Runn(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
ILogger log)
{
    string fileName = "";

    try
    {
        string storageConnectionString = "https://mystorageaccount.blob.core.windows.net/mycontainer?sp=r&st=2024-07-11T06:09:32Z&se=2025-05-01T14:09:32Z&sv=2022-11-02&sr=c&sig=ObUpZOmxWAVqmrbWc0X52xbSRMf8XUc%2BGau2esCzlDE%3D";
        string containerName = "mycontainer";

        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageConnectionString);
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
        CloudBlobContainer container = blobClient.GetContainerReference(containerName);

        // Create the container if it doesn't exist
        await container.CreateIfNotExistsAsync();

        // Get a reference to a blob in the container
        string directoryName = "Backups";
        CloudBlobDirectory directory = container.GetDirectoryReference(directoryName);

        // Get the file name from the request
        fileName = "one.xml";
        XmlDocument xmlDoc = GetXmlDocument(); ///Gets the XmlDocument from FTP
        MemoryStream xmlStream = new MemoryStream();
        xmlDoc.Save(xmlStream);            
        xmlStream.Position = 0;
        
        // Retrieve the file from the request body
        var requestBody = await new StreamReader(xmlStream).ReadToEndAsync();
        byte[] fileBytes = Convert.FromBase64String(requestBody);

        // Upload the file to Azure Blob Storage
        CloudBlockBlob blob = directory.GetBlockBlobReference(fileName);
        using (var stream = new MemoryStream(fileBytes))
        {
            await blob.UploadFromStreamAsync(stream);
        }            
    }
    catch (Exception ex)
    {
        log.LogError($"Error downloading file from FTP: {ex.Message}");
        return new StatusCodeResult(StatusCodes.Status500InternalServerError);
    }

    return new OkObjectResult($"File uploaded successfully: {fileName}");
}

When I run the code in my local, the console shows this error:

enter image description here

So, I added the parameter AzureWebJobsSecretStorageType:"Files" in local.settings.json, and it still shows the same error. I have not published this code to Azure yet.


Solution

  • The connection string should be generated to allow the app to anonymously connect and perform the read operation:

    Your connection string is missing the SAS access data in the connection string:

    The string is missing the SharedAccessSignature:

    SharedAccessSignature=us=2022-11-02&ss=bfq&srt=co&sp=wct&se=2024-06-12T12:28:54Z&st=2023-06-12T04:28:54Z&spr=https
    

    It should be in the connection string:

        string storageConnectionString = "https://mystorageaccount.blob.core.windows.net/mycontainer?sp=r&st=2024-07-11T06:09:32Z&se=2025-05-01T14:09:32Z&sv=2022-11-02&sr=c&sig=ObUpZOmxWAVqmrbWc0X52xbSRMf8XUc%2BGau2esCzlDE%3D";
    

    You can generate it from Azure portal with CLI or manually: https://learn.microsoft.com/en-us/azure/data-explorer/kusto/api/connection-strings/generate-sas-token#azure-portal