Home >Backend Development >C++ >How to Recursively Download All Files and Subdirectories via FTP in C#?

How to Recursively Download All Files and Subdirectories via FTP in C#?

DDD
DDDOriginal
2025-01-12 14:56:43576browse

How to Recursively Download All Files and Subdirectories via FTP in C#?

C# FTP recursive download of files and subdirectories

When using FTP to automatically synchronize files, you often encounter problems downloading files and subdirectories. This is usually accompanied by a 550 error since the folder is treated as a file to be downloaded.

Identify files and directories

FTP itself does not clearly distinguish between files and directories. Therefore, other methods are needed to identify their types.

  • Attempting to download file: If an attempt to download "file" fails, it may be a directory.
  • File extension: This can be used to differentiate between files and directories when the file extensions for files in a specific directory are consistent.
  • Server-specific directory listing: Parses the server's response to a directory listing command (e.g., LIST). Some servers use specific characters or symbols to indicate directories.

Recursive file download

To download all files (including those in subdirectories), follow these steps:

  1. List remote directories and retrieve directory listings.
  2. Loop through the list and differentiate between files and directories.
  3. For files, download them as usual.
  4. For directories, repeat steps 1-3 recursively to retrieve files in subdirectories.

Code implementation

The following code example demonstrates recursive file downloading using the FtpWebRequest class, assuming *nix-style directory listings are used:

<code class="language-csharp">using System;
using System.IO;
using System.Net;

public class FtpDownload
{
    public static void DownloadFtpDirectory(string url, NetworkCredential credentials, string localPath)
    {
        FtpWebRequest listRequest = (FtpWebRequest)WebRequest.Create(url);
        listRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
        listRequest.Credentials = credentials;

        var lines = new System.Collections.Generic.List<string>();

        using (var listResponse = (FtpWebResponse)listRequest.GetResponse())
        using (Stream listStream = listResponse.GetResponseStream())
        using (var listReader = new StreamReader(listStream))
        {
            while (!listReader.EndOfStream)
            {
                lines.Add(listReader.ReadLine());
            }
        }

        foreach (string line in lines)
        {
            string[] tokens = line.Split(new[] { ' ' }, 9, StringSplitOptions.RemoveEmptyEntries);
            string name = tokens[8];
            string permissions = tokens[0];

            string localFilePath = Path.Combine(localPath, name);
            string fileUrl = url + name;

            if (permissions[0] == 'd')
            {
                if (!Directory.Exists(localFilePath))
                {
                    Directory.CreateDirectory(localFilePath);
                }

                DownloadFtpDirectory(fileUrl + "/", credentials, localFilePath);
            }
            else
            {
                FtpWebRequest downloadRequest = (FtpWebRequest)WebRequest.Create(fileUrl);
                downloadRequest.Method = WebRequestMethods.Ftp.DownloadFile;
                downloadRequest.Credentials = credentials;

                using (FtpWebResponse downloadResponse = (FtpWebResponse)downloadRequest.GetResponse())
                using (Stream sourceStream = downloadResponse.GetResponseStream())
                using (Stream targetStream = File.Create(localFilePath))
                {
                    byte[] buffer = new byte[10240];
                    int read;
                    while ((read = sourceStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        targetStream.Write(buffer, 0, read);
                    }
                }
            }
        }
    }
}</code>

Alternative library

For enhanced functionality and support for MLSD commands, consider using a third-party library such as WinSCP.NET. This library simplifies recursive downloading and supports various server-specific directory listing formats.

<code class="language-csharp">using System;
using System.IO;
using WinSCP;

public class FtpDownloadWithLibrary
{
    public static void DownloadFtpDirectory(string url, NetworkCredential credentials, string localPath)
    {
        // 设置会话选项
        SessionOptions sessionOptions = new SessionOptions
        {
            Protocol = Protocol.Ftp,
            HostName = host, // 请替换为你的主机名
            UserName = user, // 请替换为你的用户名
            Password = password, // 请替换为你的密码
        };

        using (Session session = new Session())
        {
            // 连接
            session.Open(sessionOptions);

            // 下载文件
            session.GetFiles(url, localPath).Check();
        }
    }
}</code>

Please note that in the FtpDownloadWithLibrary example you need to replace host, user, password with your actual FTP server information. And you need to install the WinSCP.NET library.

The above is the detailed content of How to Recursively Download All Files and Subdirectories via FTP in C#?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn