Read file from FTP to memory in C#

2019-01-12 03:10发布

问题:

I want to read a file from a FTP server without downloading it to a local file. I wrote a function but it does not work:

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

回答1:

Here's a simple working example using your code to grab a file from the Microsoft public FTP servers:

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

I reckon you're missing a slash on this line here in your code:

string url = FtpPath + FileName;

Perhaps between FtpPath and FileName ?



回答2:

Small binary file

If the file is small, the easiest way is using 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);

Small text file

If the small file is a text file, use WebClient.DownloadString:

string contents = client.DownloadString(url);

It assumes that the file contents is in UTF-8 encoding (a plain ASCII file will do too). If you need to use a different encoding, use WebClient.Encoding property.


Large binary file

If the file is large, so that you need to process it in chunks, instead of loading it to memory whole, use 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"
    }
}

Large text file

If the large file is a text file and you want to process it by lines, instead of by chunks of a fixed size, use 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);
    }
}

Again, this assumes UTF-8 encoding. If you want to use another encoding, use an overload of StreamReader constructor that takes also Encoding.



回答3:

The code you have above is very simillar to another Stackoverlow example I found and used myself 2 days ago. Provided you set the URI, User and Password correctly, it will download the file and set the contents to FileString. I'm not sure what you mean by wanting to read the file without downloading it. This is not really an option.

If you want to look at file attributes (I see you mention "version"), you could use the code below to get all the file Name, Data, and Size from the FTP server without downloading the file.

Call GetFileInfo and pass in the file name (make sure you follow through the code to set the full FTP path, User and Password). This will give you back a FTPFileInfo object with a Name, Date and Size.

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


回答4:

It is impossible to know what the issue is without details about the error/exception.

At a guess, you do not seem to be assigning a new value to version after the initial declaration

string version = "";

Try changing your code to

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


回答5:

C Sharp GUI app. Minimal ftp transfer, not elegant but it works fine. GUI, not console.

Weather from noaa. Find your region (look for your metar)! A METAR weather report is predominantly used by pilots in fulfillment of a part of a pre- flight

Build with vs 2012 premium RC (july 2012)

(click on label, not button)

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;

        }
    }
}


回答6:

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


回答7:

I know this is an old question, but I thought I'd suggest using path.combine for the next guy reading this. Helps clean up these kinds of issues.

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


回答8:

We can use below method to get the file attribute from ftp without downloading the file.This is working fine for me.

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


回答9:

Take a look at my FTP class, it might be exactly what you need.

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

To initialize:

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