You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否通过Azure Function的FTP触发器实现FTP新增文件触发与C#处理?

实现FTP新增文件触发Azure Function(C#)的方案

以下是三种不依赖Logic Apps FTP连接器、纯靠Azure Function和C#实现的方案:

方案1:Timer Trigger轮询FTP服务器

这是最通用的方案,适用于所有FTP服务器,核心思路是定时检查FTP目录,对比已处理文件列表找出新增文件。

  • 核心步骤:

    1. 创建带TimerTrigger的Azure Function,设置轮询频率(比如每分钟一次,表达式0 */1 * * * *)
    2. 用C#的FTP客户端库(推荐FluentFTP,NuGet可安装)连接FTP服务器,获取目标目录的文件列表
    3. 在Azure Storage(Blob或Table)中存储已处理的文件名/唯一标识,避免重复处理
    4. 对比新拉取的文件列表和已处理列表,对新增文件执行下载、处理逻辑
    5. 处理完成后更新已处理文件列表到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端点,跳过轮询步骤。

  • 核心步骤:

    1. 创建带HttpTrigger的Azure Function,启用API密钥验证防止非法调用
    2. 在FTP服务器配置中,设置当文件上传完成时,发送HTTP POST请求到Function的端点,携带文件名、路径等信息
    3. Function接收到请求后,用FTP客户端连接服务器下载对应文件并处理
    4. 处理完成后返回成功响应给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监控和文件处理逻辑。

  • 核心步骤:

    1. 创建一个Timer Trigger Function(或本地服务)负责监控FTP目录,发现新文件就把文件信息(路径、文件名)写入Azure Storage Queue
    2. 创建一个QueueTrigger的Azure Function,监听Queue消息,取出文件信息后连接FTP下载并处理
    3. Queue自动处理重试、死信队列,避免处理失败丢失任务
  • 优势:

    • 解耦监控和处理,可独立调整两者的资源配置
    • Queue提供重试机制,处理失败的任务会自动重新入队(可配置重试次数)
    • 支持削峰,当大量文件上传时,Queue会缓存任务,Function逐步处理

内容的提问来源于stack exchange,提问作者cgsabari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 20:05:53