问题
I have an FTP source that adds daily file and I need to copy the files on daily basis from FTP to blob storage using FluentFTP library in azure function
I am using C# in Azure function, and I did all the coding part but missing to download the file from FTP to copy it directly to the blob destination.
//#r "FluentFTP"
#r "Newtonsoft.Json"
#r "System.Data"
#r "Microsoft.WindowsAzure.Storage"
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Globalization;
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using FluentFTP;
public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
string blobConnectionString = "ConnectionString";
// Gestione BLOB Storage
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(blobConnectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("out");
using (FtpClient conn = new FtpClient())
{
conn.Host = "ftp server";
conn.Credentials = new NetworkCredential("username", "pass");
// get a list of files and directories in the "/OUT" folder
foreach (FtpListItem item in conn.GetListing("/OUT"))
{
// if this is a file and ends with CSV
if (
item.Type == FtpFileSystemObjectType.File
&&
item.FullName.ToLower().EndsWith(".csv")
)
{
string yyyy = item.FullName.Substring(10,4);
string mm = item.FullName.Substring(14,2);
string dd = item.FullName.Substring(16,2);
var fileName = "out/brt/" + yyyy + "/"+ mm + "/"+ dd + "/" + item.Name;
CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
// download the file
conn.DownloadFile( blockBlob , item.FullName);
}
}
return new OkObjectResult($"Hello");
}
}
If I can use a blob container as a destination for the FluentFTP function then it would be the best, but this way I am getting the error that this blob block that I am using is not an a destination
This is the error that I am getting
cannot convert from 'Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob' to 'string'
I don't know if there is another way to download the file locally so I can upload it to the blob instead of using this client.DownloadFile
function.
回答1:
It's probably not possible with Fluent FTP.
There's FtpClient.Download
method which takes Stream
.
public bool Download(Stream outStream, string remotePath, IProgress<double> progress = null)
But it does not look like there's API to get "blob upload Stream".
Conversely, you cannot get "FTP download Stream" from FluentFTP (which you would be able to use with blob API).
But you can use native .NET FtpWebRequest
FTP client, which has API to get "FTP download Stream":
public static async System.Threading.Tasks.Task RunAsync([TimerTrigger("0 */1 * * * *")]TimerInfo myTimer, ILogger log)
{
var ftpUserName = "xxxxxx";
var ftpPassword = "xxxxxxxxx";
var filename = "test.png";
string blobConnectionString = "xxxxxxx";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(blobConnectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("myblobcontainer");
FtpWebRequest fileRequest = (FtpWebRequest)WebRequest.Create("ftp://xxxxxx/" + filename);
fileRequest.Method = WebRequestMethods.Ftp.DownloadFile;
fileRequest.Credentials = new NetworkCredential(ftpUserName, ftpPassword);
FtpWebResponse fileResponse = (FtpWebResponse)fileRequest.GetResponse();
Stream fileStream = fileResponse.GetResponseStream();
CloudBlockBlob blockBlob = container.GetBlockBlobReference(filename);
await blockBlob.UploadFromStreamAsync(fileStream);
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
}
回答2:
If you want to use FluentFTP, you can get a blob upload stream using one of these two methods:
- CloudBlockBlob.OpenWrite()
- CloudBlockBlob.OpenWriteAsync()
Then you can use the FTPClient.Download
method which takes a Stream
public bool Download(Stream outStream, string remotePath, IProgress<double> progress = null)
Something like this:
[FunctionName("HttpTriggerCSharp")]
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
var ftpHost = "xxxxx";
var ftpUserName = "xxxx";
var ftpPassword = "xxxx";
var filename = "xxxxx";
string blobConnectionString = "xxxxxxxxxxx";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(blobConnectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("xxxxx");
FtpClient client = new FtpClient(ftpHost, ftpUserName, ftpPassword); // or set Host & Credentials
client.EncryptionMode = FtpEncryptionMode.Implicit;
client.SslProtocols = SslProtocols.None;
client.ValidateCertificate += new FtpSslValidation(OnValidateCertificate);
client.Connect();
void OnValidateCertificate(FtpClient control, FtpSslValidationEventArgs e) {
// add logic to test if certificate is valid here
e.Accept = true;
}
CloudBlockBlob blockBlob = container.GetBlockBlobReference(filename);
var outStream = blockBlob.OpenWrite();
client.Download(outStream,filename);
outStream.Commit(); // I'm not sure if this is needed?
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
return (ActionResult)new OkObjectResult($"Action succeeded.");
}
回答3:
You cannot directly move the files from the FTP to Blob using the SDK. You have to download the files temporarily first - either into a stream (depending how large they become) or to a temp file.
However, if all you want to do is to move files from FTP to Blob on a schedule, I would actually look into using Azure Data Factory which is built exactly for tasks like that: https://docs.microsoft.com/en-us/azure/data-factory/connector-ftp
来源:https://stackoverflow.com/questions/56847967/azure-function-to-copy-files-from-ftp-to-blob-storage-using-fluentftp