在 C# 中将文件从 FTP 读取到内存

本文关键字:FTP 读取 内存 文件 | 更新日期: 2023-09-27 17:57:15

我想从FTP服务器读取文件而不将其下载到本地文件。我写了一个函数,但它不起作用:

private string GetServerVersion()
{
    WebClient request = new WebClient();
    string url = FtpPath + FileName;
    string version = "";
    request.Credentials = new NetworkCredential(ftp_user, ftp_pas);
    try
    {
        byte[] newFileData = request.DownloadData(new Uri(FtpPath)+FileName);
        string fileString = System.Text.Encoding.UTF8.GetString(newFileData);
    }
    catch (WebException e)
    {
    }
    return version;
}

在 C# 中将文件从 FTP 读取到内存

下面是一个简单的工作示例,使用您的代码从Microsoft公共 FTP 服务器获取文件:

WebClient request = new WebClient();
string url = "ftp://ftp.microsoft.com/developr/fortran/" +"README.TXT";
request.Credentials = new NetworkCredential("anonymous", "anonymous@example.com");
try
{
  byte[] newFileData = request.DownloadData(url);
  string fileString = System.Text.Encoding.UTF8.GetString(newFileData);
  Console.WriteLine(fileString);
}
catch (WebException e)
{
  // Do something such as log error, but this is based on OP's original code
  // so for now we do nothing.
}

我认为您在代码中的这一行缺少斜杠:

string url = FtpPath + FileName;

也许在FtpPathFileName之间?

小二进制文件

如果文件很小,最简单的方法是使用 WebClient.DownloadData

WebClient client = new WebClient();
string url = "ftp://ftp.example.com/remote/path/file.zip";
client.Credentials = new NetworkCredential("username", "password");
byte[] contents = client.DownloadData(url);
<小时 />

小文本文件

如果小文件是文本文件,请使用WebClient.DownloadString

string contents = client.DownloadString(url);

它假定文件内容采用 UTF-8 编码(纯 ASCII 文件也可以)。如果需要使用其他编码,请使用WebClient.Encoding属性。

<小时 />

大型二进制文件

如果文件很大,因此您需要分块处理它,而不是将其加载到整个内存中,请使用 FtpWebRequest

FtpWebRequest request =
    (FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/remote/path/file.zip");
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Ftp.DownloadFile;
using (Stream stream = request.GetResponse().GetResponseStream())
{
    byte[] buffer = new byte[10240];
    int read;
    while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
    {
        // process the chunk in "buffer"
    }
}

您还可以通过使用 WebClient.OpenRead 来简化代码。

<小时 />

大型文本文件

如果大文件是文本文件,并且您希望按行而不是固定大小的块处理它,请使用 StreamReader

FtpWebRequest request =
    (FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/remote/path/file.txt");
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Ftp.DownloadFile;
using (Stream stream = request.GetResponse().GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
    while (!reader.EndOfStream)
    {
        string line = reader.ReadLine();
        // process the line
        Console.WriteLine(line);
    }
}

同样,这假定使用 UTF-8 编码。如果要使用其他编码,请使用StreamReader构造函数的重载,该构造函数也需要Encoding

与前面一样,您可以使用 WebClient.OpenRead 来简化代码。

<小时 />

流接口

但是,在许多情况下,您需要在某个使用 Stream 接口的 API 中使用下载的数据。在这种情况下,不要使用上述任何解决方案,而是直接使用 API 中的request.GetResponse().GetResponseStream()WebClient.OpenRead返回的流。

有关示例,请参阅在 C# 中将文件从 FTP 直接传输到 Azure Blob 存储。

您上面的代码与我 2 天前发现并使用的另一个 Stackoverlow 示例非常相似。 如果您正确设置了 URI、用户和密码,它将下载文件并将内容设置为 FileString。 我不确定您想在不下载文件的情况下阅读文件是什么意思。 这不是一个真正的选择。

如果你想查看文件属性(我看到你提到了"版本"),你可以使用下面的代码从FTP服务器获取所有文件名,数据和大小,而无需下载文件。

调用 GetFileInfo 并传入文件名(确保按照代码设置完整的 FTP 路径、用户和密码)。 这将返回一个具有名称、日期和大小的 FTPFileInfo 对象。

  public static FTPFileInfo GetFileInfo(string fileName)
        {
            var dirInfo = WordstockExport.GetFTPDirectoryDetails();
            var list = FTPFileInfo.Load(dirInfo);
            try
            {
                FTPFileInfo ftpFile = list.SingleOrDefault(f => f.FileName == fileName);
                return ftpFile;
            }
            catch { }
            return null;
        }
     class FTPFileInfo
        {
            private DateTime _FileDate;
            private long _FileSize;
            private string _FileName;
            public DateTime FileDate
            {
                get { return _FileDate; }
                set { _FileDate = value; }
            }
            public long FileSize
            {
                get { return _FileSize; }
                set { _FileSize = value; }
            }
            public string FileName
            {
                get { return _FileName; }
                set { _FileName = value; }
            }
            public FTPFileInfo() { }
            public static FTPFileInfo LoadFromLine(string line)
            {
                FTPFileInfo file = new FTPFileInfo();
                string[] ftpFileInfo = line.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                file._FileDate = DateTime.Parse(ftpFileInfo[0] + " " + ftpFileInfo[1]);
                file._FileSize = long.Parse(ftpFileInfo[2]);
                file._FileName = ftpFileInfo[3];
                return file;
            }
            public static List<FTPFileInfo> Load(string listDirectoryDetails)
            {
                List<FTPFileInfo> files = new List<FTPFileInfo>();
                string[] lines = listDirectoryDetails.Split("'r'n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                foreach(var line in lines)
                    files.Add(LoadFromLine(line));
                return files;
            }
        }
       private static string GetFTPDirectoryDetails()
            {
                FtpWebRequest request = (FtpWebRequest)WebRequest.Create(App.Export_FTPPath);
                request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
                request.Credentials = new NetworkCredential(App.FTP_User, App.FTP_Password);
                FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                Stream responseStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(responseStream);
                string fileLines = reader.ReadToEnd();
                reader.Close();
                response.Close();
                return fileLines;
            }

如果没有有关错误/异常的详细信息,就不可能知道问题是什么。

猜测,您似乎没有在初始声明后为version分配新值

string version = "";

尝试将代码更改为

version = System.Text.Encoding.UTF8.GetString(newFileData);

C Sharp GUI 应用程序。 最小的ftp传输,不优雅,但工作正常。GUI,而不是控制台。

来自诺阿的天气。找到你的地区(寻找你的元)!METAR天气报告主要由飞行员用于完成飞行前

的一部分使用 vs 2012

高级 RC 构建(2012 年 7 月)

(点击标签,而不是按钮)

using System;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Collections.Generic;
namespace getweather
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        } 
         private void button2_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
        private void CYYY_Click(object sender, EventArgs e)
        {
            WebClient request = new WebClient();
            string url = "ftp://tgftp.nws.noaa.gov/data/observations/metar/decoded/CYYY.TXT";
            request.Credentials = new NetworkCredential("anonymous", "anonymous@example.com");
            byte[] newFileData = request.DownloadData(url);
            string fileString = System.Text.Encoding.UTF8.GetString(newFileData);
            richTextBox1.Text = fileString;
        }
        private void CYSC_Click(object sender, EventArgs e)
        {
            WebClient request = new WebClient();
            string url = "ftp://tgftp.nws.noaa.gov/data/observations/metar/decoded/CYSC.TXT";
            request.Credentials = new NetworkCredential("anonymous", "anonymous@example.com");
            byte[] newFileData = request.DownloadData(url);
            string fileString = System.Text.Encoding.UTF8.GetString(newFileData);
            richTextBox1.Text = fileString;
        }
        private void CYQB_Click(object sender, EventArgs e)
        {
            WebClient request = new WebClient();
            string url = "ftp://tgftp.nws.noaa.gov/data/observations/metar/decoded/CYQB.TXT";
            request.Credentials = new NetworkCredential("anonymous", "anonymous@example.com");
            byte[] newFileData = request.DownloadData(url);
            string fileString = System.Text.Encoding.UTF8.GetString(newFileData);
            richTextBox1.Text = fileString;
        }
        private void CYUY_Click(object sender, EventArgs e)
        {
            WebClient request = new WebClient();
            string url = "ftp://tgftp.nws.noaa.gov/data/observations/metar/decoded/CYUY.TXT";
            request.Credentials = new NetworkCredential("anonymous", "anonymous@example.com");
            byte[] newFileData = request.DownloadData(url);
            string fileString = System.Text.Encoding.UTF8.GetString(newFileData);
            richTextBox1.Text = fileString;
        }
        private void CYHU_Click(object sender, EventArgs e)
        {
            WebClient request = new WebClient();
            string url = "ftp://tgftp.nws.noaa.gov/data/observations/metar/decoded/CYHU.TXT";
            request.Credentials = new NetworkCredential("anonymous", "anonymous@example.com");
            byte[] newFileData = request.DownloadData(url);
            string fileString = System.Text.Encoding.UTF8.GetString(newFileData);
            richTextBox1.Text = fileString;
        }
    }
}
WebClient request = new WebClient();
string url = "ftp://ftp.microsoft.com/developr/fortran/" +"README.TXT";
request.Credentials = new NetworkCredential("anonymous", "anonymous@example.com");
request.Proxy = null;
try
{
  byte[] newFileData = request.DownloadData(url);
  string fileString = System.Text.Encoding.UTF8.GetString(newFileData);
  Console.WriteLine(fileString);
}
catch (WebException e)
{
  // Do something such as log error, but this is based on OP's original code
  // so for now we do nothing.
}
我知道

这是一个老问题,但我想我建议下一个阅读本文的人使用 path.combe。 帮助清理此类问题。

        string url = Path.Combine("ftp://ftp.microsoft.com/developr/fortran", "README.TXT");

我们可以使用以下方法从 ftp 获取文件属性,而无需下载文件。这对我来说很好用。

    public DataTable getFileListFTP(string serverIP,string userID,string Password)
    {
        DataTable dt = new DataTable();
        string[] fileListArr;
        string fileName = string.Empty;
        long fileSize = 0;
       // DateTime creationDate;
        string creationDate;
        FtpWebRequest Request = (FtpWebRequest)WebRequest.Create(serverIP);
        Request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
        Request.Credentials = new NetworkCredential(userID,Password);
        FtpWebResponse Response = (FtpWebResponse)Request.GetResponse();
        Stream ResponseStream = Response.GetResponseStream();
        StreamReader Reader = new StreamReader(ResponseStream);
        dt.Columns.Add("FileName", typeof(String));
        dt.Columns.Add("FileSize", typeof(String));
        dt.Columns.Add("CreationDate", typeof(DateTime));
        //CultureInfo c = new CultureInfo("ES-ES");
        while (!Reader.EndOfStream)//Read file name   
        {
            fileListArr = Convert.ToString(Reader.ReadLine()).Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            fileSize = long.Parse(fileListArr[4]);
            creationDate = fileListArr[6] + " " + fileListArr[5] + " " + fileListArr[7];
            //creationDate =Convert.ToDateTime(fileListArr[6] + " " + fileListArr[5] + " " + fileListArr[7], c).ToString("dd/MMM/yyyy", DateTimeFormatInfo.InvariantInfo);
            fileName = Convert.ToString(fileListArr[8]);
            DataRow drow = dt.NewRow();
            drow["FileName"] = fileName;
            drow["FileSize"] = fileName;
            drow["CreationDate"] = creationDate;
            dt.Rows.Add(drow);
        }
        Response.Close();
        ResponseStream.Close();
        Reader.Close();
        return dt;
    }

看看我的FTP类,它可能正是你所需要的。

Public Class FTP
        '-------------------------[BroCode]--------------------------
        '----------------------------FTP-----------------------------
        Private _credentials As System.Net.NetworkCredential
        Sub New(ByVal _FTPUser As String, ByVal _FTPPass As String)
            setCredentials(_FTPUser, _FTPPass)
        End Sub
        Public Sub UploadFile(ByVal _FileName As String, ByVal _UploadPath As String)
            Dim _FileInfo As New System.IO.FileInfo(_FileName)
            Dim _FtpWebRequest As System.Net.FtpWebRequest = CType(System.Net.FtpWebRequest.Create(New Uri(_UploadPath)), System.Net.FtpWebRequest)
            _FtpWebRequest.Credentials = _credentials
            _FtpWebRequest.KeepAlive = False
            _FtpWebRequest.Timeout = 20000
            _FtpWebRequest.Method = System.Net.WebRequestMethods.Ftp.UploadFile
            _FtpWebRequest.UseBinary = True
            _FtpWebRequest.ContentLength = _FileInfo.Length
            Dim buffLength As Integer = 2048
            Dim buff(buffLength - 1) As Byte
            Dim _FileStream As System.IO.FileStream = _FileInfo.OpenRead()
            Try
                Dim _Stream As System.IO.Stream = _FtpWebRequest.GetRequestStream()
                Dim contentLen As Integer = _FileStream.Read(buff, 0, buffLength)
                Do While contentLen <> 0
                    _Stream.Write(buff, 0, contentLen)
                    contentLen = _FileStream.Read(buff, 0, buffLength)
                Loop
                _Stream.Close()
                _Stream.Dispose()
                _FileStream.Close()
                _FileStream.Dispose()
            Catch ex As Exception
                MessageBox.Show(ex.Message, "Upload Error: ", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try
        End Sub
        Public Sub DownloadFile(ByVal _FileName As String, ByVal _ftpDownloadPath As String)
            Try
                Dim _request As System.Net.FtpWebRequest = System.Net.WebRequest.Create(_ftpDownloadPath)
                _request.KeepAlive = False
                _request.Method = System.Net.WebRequestMethods.Ftp.DownloadFile
                _request.Credentials = _credentials
                Dim _response As System.Net.FtpWebResponse = _request.GetResponse()
                Dim responseStream As System.IO.Stream = _response.GetResponseStream()
                Dim fs As New System.IO.FileStream(_FileName, System.IO.FileMode.Create)
                responseStream.CopyTo(fs)
                responseStream.Close()
                _response.Close()
            Catch ex As Exception
                MessageBox.Show(ex.Message, "Download Error: ", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try
        End Sub
        Public Function GetDirectory(ByVal _ftpPath As String) As List(Of String)
            Dim ret As New List(Of String)
            Try
                Dim _request As System.Net.FtpWebRequest = System.Net.WebRequest.Create(_ftpPath)
                _request.KeepAlive = False
                _request.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails
                _request.Credentials = _credentials
                Dim _response As System.Net.FtpWebResponse = _request.GetResponse()
                Dim responseStream As System.IO.Stream = _response.GetResponseStream()
                Dim _reader As System.IO.StreamReader = New System.IO.StreamReader(responseStream)
                Dim FileData As String = _reader.ReadToEnd
                Dim Lines() As String = FileData.Split(New String() {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
                For Each l As String In Lines
                    ret.Add(l)
                Next
                _reader.Close()
                _response.Close()
            Catch ex As Exception
                MessageBox.Show(ex.Message, "Directory Fetch Error: ", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try
            Return ret
        End Function
        Private Sub setCredentials(ByVal _FTPUser As String, ByVal _FTPPass As String)
            _credentials = New System.Net.NetworkCredential(_FTPUser, _FTPPass)
        End Sub
    End Class

要初始化:

Dim ftp As New FORM.FTP("username", "password")
ftp.UploadFile("c:'file.jpeg", "ftp://domain/file.jpeg")
ftp.DownloadFile("c:'file.jpeg", "ftp://ftp://domain/file.jpeg")
Dim directory As List(Of String) = ftp.GetDirectory("ftp://ftp.domain.net/")
        ListBox1.Items.Clear()
        For Each item As String In directory
            ListBox1.Items.Add(item)
        Next

https://stackoverflow.com/a/28669746/2701974