能否通过Azure Function的FTP触发器实现FTP新增文件触发与C#处理?
实现FTP新增文件触发Azure Function(C#)的方案
以下是三种不依赖Logic Apps FTP连接器、纯靠Azure Function和C#实现的方案:
方案1:Timer Trigger轮询FTP服务器
这是最通用的方案,适用于所有FTP服务器,核心思路是定时检查FTP目录,对比已处理文件列表找出新增文件。
核心步骤:
- 创建带
TimerTrigger的Azure Function,设置轮询频率(比如每分钟一次,表达式0 */1 * * * *) - 用C#的FTP客户端库(推荐
FluentFTP,NuGet可安装)连接FTP服务器,获取目标目录的文件列表 - 在Azure Storage(Blob或Table)中存储已处理的文件名/唯一标识,避免重复处理
- 对比新拉取的文件列表和已处理列表,对新增文件执行下载、处理逻辑
- 处理完成后更新已处理文件列表到Storage
- 创建带
简化代码示例:
using System; using System.IO; using System.Collections.Generic; using System.Threading.Tasks; using FluentFTP; using Microsoft.Azure.WebJobs; using Microsoft.Extensions.Logging; using Azure.Storage.Blobs; public class FtpPollingFunction { private readonly BlobContainerClient _processedFilesContainer; // 通过依赖注入获取Blob容器客户端(需配置连接字符串) public FtpPollingFunction(BlobContainerClient blobContainerClient) { _processedFilesContainer = blobContainerClient; } [FunctionName("FtpNewFilePoller")] public async Task Run([TimerTrigger("0 */1 * * * *")] TimerInfo timer, ILogger log) { log.LogInformation($"Starting FTP poll at {DateTime.UtcNow}"); // 初始化FTP客户端 using var ftpClient = new FtpClient("ftp.your-server.com", "ftp-username", "ftp-password"); await ftpClient.ConnectAsync(); // 获取目标目录文件列表 var ftpFiles = await ftpClient.GetListingAsync("/upload-directory"); var newFiles = ftpFiles.Where(f => f.Type == FtpObjectType.File).ToList(); // 读取已处理文件记录 var processedBlob = _processedFilesContainer.GetBlobClient("processed-files.txt"); var processedFiles = new HashSet<string>(); if (await processedBlob.ExistsAsync()) { var content = await processedBlob.DownloadContentAsync(); processedFiles = new HashSet<string>(content.Value.Content.ToString().Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries)); } // 处理新增文件 foreach (var file in newFiles.Where(f => !processedFiles.Contains(f.Name))) { log.LogInformation($"Processing file: {file.Name}"); // 下载文件到内存流 using var fileStream = new MemoryStream(); await ftpClient.DownloadAsync(fileStream, file.FullName); fileStream.Position = 0; // 执行自定义处理逻辑(示例:读取文本内容) var fileContent = new StreamReader(fileStream).ReadToEnd(); // TODO: 替换为你的业务处理逻辑,比如写入DB、调用API等 // 标记文件为已处理 processedFiles.Add(file.Name); } // 更新已处理文件记录到Blob await processedBlob.UploadAsync( new MemoryStream(System.Text.Encoding.UTF8.GetBytes(string.Join(Environment.NewLine, processedFiles))), overwrite: true); await ftpClient.DisconnectAsync(); log.LogInformation($"FTP poll completed at {DateTime.UtcNow}"); } }
- 注意事项:
- 不要硬编码FTP密码,用Azure Key Vault存储,通过Function托管身份访问
- 调整轮询频率平衡实时性和服务器负载
- 给FTP操作添加异常捕获和重试逻辑,避免单次失败导致整个轮询中断
方案2:利用FTP服务器的事件通知触发HTTP Function
如果你的FTP服务器支持上传完成事件触发(比如FileZilla Server、IIS FTP),可以直接让FTP服务器调用Azure Function的HTTP端点,跳过轮询步骤。
核心步骤:
- 创建带
HttpTrigger的Azure Function,启用API密钥验证防止非法调用 - 在FTP服务器配置中,设置当文件上传完成时,发送HTTP POST请求到Function的端点,携带文件名、路径等信息
- Function接收到请求后,用FTP客户端连接服务器下载对应文件并处理
- 处理完成后返回成功响应给FTP服务器
- 创建带
简化代码示例(HTTP Trigger部分):
using System.IO; using System.Threading.Tasks; using FluentFTP; using Microsoft.AspNetCore.Mvc; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.Http; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; public class FtpWebhookFunction { [FunctionName("FtpFileUploadWebhook")] public async Task<IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, ILogger log) { log.LogInformation("Received FTP file upload notification"); // 从请求体获取文件名(需和FTP服务器发送的格式匹配) var requestBody = await new StreamReader(req.Body).ReadToEndAsync(); var fileName = requestBody; // 示例,实际需解析JSON或表单数据 // 连接FTP服务器下载文件 using var ftpClient = new FtpClient("ftp.your-server.com", "ftp-username", "ftp-password"); await ftpClient.ConnectAsync(); using var fileStream = new MemoryStream(); await ftpClient.DownloadAsync(fileStream, $"/upload-directory/{fileName}"); fileStream.Position = 0; // 执行处理逻辑 ProcessFile(fileStream); await ftpClient.DisconnectAsync(); return new OkObjectResult($"File {fileName} processed successfully"); } private void ProcessFile(MemoryStream fileStream) { // 自定义处理逻辑 } }
- 注意事项:
- 确保FTP服务器的HTTP请求能访问到Azure Function的公网端点(如果Function在VNet内,需配置网络访问规则)
- 给Function设置API密钥,在FTP服务器的请求中携带
x-functions-key头部
方案3:Azure Storage Queue解耦监控与处理
如果需要更高的可靠性和可扩展性,可以用Queue作为中间层,分离FTP监控和文件处理逻辑。
核心步骤:
- 创建一个Timer Trigger Function(或本地服务)负责监控FTP目录,发现新文件就把文件信息(路径、文件名)写入Azure Storage Queue
- 创建一个
QueueTrigger的Azure Function,监听Queue消息,取出文件信息后连接FTP下载并处理 - Queue自动处理重试、死信队列,避免处理失败丢失任务
优势:
- 解耦监控和处理,可独立调整两者的资源配置
- Queue提供重试机制,处理失败的任务会自动重新入队(可配置重试次数)
- 支持削峰,当大量文件上传时,Queue会缓存任务,Function逐步处理
内容的提问来源于stack exchange,提问作者cgsabari
相关产品推荐
相关产品推荐

