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

开发接收FTP上传转HTTP POST的Web应用方案咨询(PHP/C#)

Hey there! Let's solve this problem step by step. The core challenge here is bridging the gap between your client's FTP-only XML uploads and your IIS server's need to receive that data via HTTP POST. Here's how to build a lightweight "FTP-to-HTTP proxy" that handles this seamlessly, with both C# (ideal for your Windows/IIS environment) and PHP options:

Solution Overview

We’ll deploy a minimal, purpose-built FTP server that only accepts XML file uploads. As soon as an XML file is received, the server will read its content and forward it to your target endpoint via an HTTP POST request. No full FTP server features (like downloads or directory browsing) are needed, keeping the setup secure and lightweight.


Since you’re running IIS on Windows, a C# solution integrates smoothly with your existing stack. Here’s how to implement it:

Step 1: Use a Lightweight FTP Server Library

Skip building an FTP server from scratch—use the open-source FubarDev.FtpServer library, which is designed for easy customization and event handling. Install it via NuGet:

Install-Package FubarDev.FtpServer
Install-Package FubarDev.FtpServer.FileSystem.DotNet

Step 2: Build the FTP-to-HTTP Proxy

Create a .NET Console App (convertible to a Windows Service for background running) with this core logic:

using FubarDev.FtpServer;
using FubarDev.FtpServer.FileSystem.DotNet;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

var host = new HostBuilder()
    .ConfigureServices(services =>
    {
        // Configure temp storage for uploaded files
        services.AddFtpServer(builder =>
        {
            builder.UseDotNetFileSystem(@"C:\temp\ftp_uploads"); // Replace with your temp path
            // Add user authentication here if needed (instead of anonymous)
            builder.AddAnonymousAuthentication();
        });
        services.AddSingleton<IFtpHost>(provider => provider.GetRequiredService<IFtpServerHost>());
    })
    // Uncomment below to run as a Windows Service
    // .UseWindowsService()
    .Build();

// Hook into file upload events
var ftpHost = host.Services.GetRequiredService<IFtpHost>();
ftpHost.UploadedFile += async (sender, args) =>
{
    var filePath = args.FileSystemEntry.FullName;
    if (Path.GetExtension(filePath).Equals(".xml", StringComparison.OrdinalIgnoreCase))
    {
        // Read XML content
        var xmlContent = await File.ReadAllTextAsync(filePath);
        
        // Forward via HTTP POST
        using var httpClient = new HttpClient();
        var postContent = new StringContent(xmlContent, Encoding.UTF8, "application/xml");
        var response = await httpClient.PostAsync("https://your-target-endpoint.com/upload", postContent);
        
        // Clean up and respond
        if (response.IsSuccessStatusCode)
        {
            File.Delete(filePath);
            Console.WriteLine($"Successfully forwarded XML: {filePath}");
        }
        else
        {
            Console.WriteLine($"Failed to forward XML: {response.StatusCode}");
            // Add retry logic or error logging here
        }
    }
};

await host.RunAsync();

Step 3: Deploy for Long-Term Use

  • Convert the console app to a Windows Service using the Microsoft.Extensions.Hosting.WindowsServices NuGet package (add .UseWindowsService() to the HostBuilder) to run it in the background without a console window.
  • Open your firewall for the FTP port you choose (e.g., 2121, since default port 21 may be restricted).

Key Resources & APIs

  • FubarDev.FtpServer: Docs for configuring authentication, FTPS encryption, and additional event hooks.
  • HttpClient: Built-in .NET class for HTTP requests (add retry logic with the Polly library for transient errors).
  • Polly: For robust retry policies to handle temporary HTTP endpoint failures.

PHP Solution (Cross-Platform Option)

If you prefer PHP, you can build an async FTP server using ReactPHP, which handles concurrent uploads efficiently. Here’s how:

Step 1: Set Up Dependencies

Install ReactPHP’s FTP server and HTTP client via Composer:

composer require react/ftp-server guzzlehttp/guzzle

Step 2: Build the Proxy Script

Create a CLI script (ftp-proxy.php) with this logic:

<?php
require __DIR__ . '/vendor/autoload.php';

$loop = React\EventLoop\Factory::create();
$tempDir = __DIR__ . '/temp_uploads';

// Create temp directory if it doesn't exist
if (!is_dir($tempDir)) mkdir($tempDir);

$server = new React\FtpServer\Server(function ($connection) use ($tempDir) {
    // Handle file uploads (STOR command)
    $connection->on('STOR', function ($path, $writeStream) use ($tempDir, $connection) {
        $fileName = basename($path);
        if (strtolower(pathinfo($fileName, PATHINFO_EXTENSION)) !== 'xml') {
            $connection->send('550 Only XML files are allowed');
            $writeStream->close();
            return;
        }

        $tempPath = $tempDir . '/' . uniqid() . '.xml';
        $fileStream = fopen($tempPath, 'w');
        
        // Pipe uploaded content to temp file
        $writeStream->pipe($fileStream)->on('close', function () use ($tempPath, $connection) {
            // Forward XML via HTTP POST
            $client = new GuzzleHttp\Client();
            try {
                $response = $client->post('https://your-target-endpoint.com/upload', [
                    'headers' => ['Content-Type' => 'application/xml'],
                    'body' => file_get_contents($tempPath)
                ]);
                
                if ($response->getStatusCode() >= 200 && $response->getStatusCode() < 300) {
                    unlink($tempPath);
                    $connection->send('226 Transfer complete and forwarded successfully');
                } else {
                    $connection->send('451 Failed to forward file to target endpoint');
                }
            } catch (Exception $e) {
                $connection->send('451 Error forwarding file: ' . $e->getMessage());
                // Log error details here
            }
        });
    });

    // Disable unused FTP commands for security
    $connection->on('LIST', fn() => $connection->send('550 Not supported'));
    $connection->on('RETR', fn() => $connection->send('550 Not supported'));
});

// Start server on port 2121
$server->listen(2121, '0.0.0.0', $loop);
echo "FTP proxy running on port 2121\n";
$loop->run();

Step 3: Run the Script

  • Execute via CLI: php ftp-proxy.php
  • For background running on Windows, use the nssm (Non-Sucking Service Manager) tool to wrap the script as a Windows Service.

Key Resources & APIs

  • ReactPHP FTP Server: Async, lightweight FTP implementation for handling concurrent connections.
  • Guzzle: Robust HTTP client for PHP with built-in retry middleware options.

Critical Security & Reliability Notes

  • Restrict Access: Limit FTP connections to trusted IPs, use FTPS encryption (both libraries support this), and avoid anonymous access unless absolutely necessary.
  • Validate XML: Add schema validation to ensure uploaded files match your expected format before forwarding.
  • Error Handling: Implement retry logic for HTTP POST failures, log all uploads/forwards, and set up alerts for critical errors.
  • Cleanup: Automatically delete old temp files (even failed uploads) to prevent disk space bloat.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:21:16