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

时间:2011-05-23 14:35:29

标签: c# .net ftp webclient

我想从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;
}

9 个答案:

答案 0 :(得分:24)

这是一个简单的工作示例,使用您的代码从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之间?

答案 1 :(得分:12)

小二进制文件

如果文件很小,最简单的方法是使用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 property

大型二进制文件

如果文件很大,那么您需要以块的形式处理它,而不是将其加载到整个内存中,请使用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"
    }
}

大文本文件

如果大文件是文本文件而您想按行处理,而不是按固定大小的块处理,请使用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编码。如果您想使用其他编码,请使用overload of StreamReader constructor that takes also Encoding

答案 2 :(得分:2)

上面的代码非常类似于我在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;
            }

答案 3 :(得分:0)

如果没有关于错误/异常的详细信息,就无法知道问题所在。

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

string version = "";

尝试将代码更改为

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

答案 4 :(得分:0)

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

noaa的天气。找到你的地区(寻找你的metar)! 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;

        }
    }
}

答案 5 :(得分:0)

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.
}

答案 6 :(得分:0)

我知道这是一个老问题,但我想我会建议使用path.combine为下一个读这个的人。帮助清理这些问题。

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

答案 7 :(得分:-1)

我们可以使用以下方法从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;
    }

答案 8 :(得分:-3)

看看我的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