Upload and Download a File To/From Ftp Server in C#/.Net

Upload and download a file to/from FTP server in C#/.NET

Upload

The most trivial way to upload a binary file to an FTP server using .NET framework is using WebClient.UploadFile:

WebClient client = new WebClient();
client.Credentials = new NetworkCredential("username", "password");
client.UploadFile(
"ftp://ftp.example.com/remote/path/file.zip", @"C:\local\path\file.zip");

If you need a greater control, that WebClient does not offer (like TLS/SSL encryption, ascii/text transfer mode, transfer resuming, etc), use FtpWebRequest. Easy way is to just copy a FileStream to FTP stream using Stream.CopyTo:

FtpWebRequest request =
(FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/remote/path/file.zip");
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Ftp.UploadFile;

using (Stream fileStream = File.OpenRead(@"C:\local\path\file.zip"))
using (Stream ftpStream = request.GetRequestStream())
{
fileStream.CopyTo(ftpStream);
}

If you need to monitor an upload progress, you have to copy the contents by chunks yourself:

FtpWebRequest request =
(FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/remote/path/file.zip");
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Ftp.UploadFile;

using (Stream fileStream = File.OpenRead(@"C:\local\path\file.zip"))
using (Stream ftpStream = request.GetRequestStream())
{
byte[] buffer = new byte[10240];
int read;
while ((read = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
ftpStream.Write(buffer, 0, read);
Console.WriteLine("Uploaded {0} bytes", fileStream.Position);
}
}

For GUI progress (WinForms ProgressBar), see:

How can we show progress bar for upload with FtpWebRequest

If you want to upload all files from a folder, see

Recursive upload to FTP server in C#.



Download

The most trivial way to download a binary file from an FTP server using .NET framework is using WebClient.DownloadFile:

WebClient client = new WebClient();
client.Credentials = new NetworkCredential("username", "password");
client.DownloadFile(
"ftp://ftp.example.com/remote/path/file.zip", @"C:\local\path\file.zip");

If you need a greater control, that WebClient does not offer (like TLS/SSL encryption, ascii/text transfer mode, resuming transfers, etc), use FtpWebRequest. Easy way is to just copy an FTP response stream to FileStream using Stream.CopyTo:

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 ftpStream = request.GetResponse().GetResponseStream())
using (Stream fileStream = File.Create(@"C:\local\path\file.zip"))
{
ftpStream.CopyTo(fileStream);
}

If you need to monitor a download progress, you have to copy the contents by chunks yourself:

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 ftpStream = request.GetResponse().GetResponseStream())
using (Stream fileStream = File.Create(@"C:\local\path\file.zip"))
{
byte[] buffer = new byte[10240];
int read;
while ((read = ftpStream.Read(buffer, 0, buffer.Length)) > 0)
{
fileStream.Write(buffer, 0, read);
Console.WriteLine("Downloaded {0} bytes", fileStream.Position);
}
}

For GUI progress (WinForms ProgressBar), see:

FtpWebRequest FTP download with ProgressBar

If you want to download all files from a remote folder, see

C# Download all files and subdirectories through FTP.

Download file from url and upload into ftp

I think your problem is that your url is missing the file name. If I remember correctly you must pass the file name in the URL. So it would look something like this:

"ftp://192.168.1.1/SampleFiles/file.txt"

How to Download file from one FTP and then Upload file to different FTP?

You were so close! Use a stream to convert your download into a byte array for upload.

I recently made a program to do just this! This will currently copy all files from one FTP directory to another so long as there is not a file in the target directory with the same name. It would be easy to change if you only wanted to copy one file, just use the copyFile, toByteArray and upload functions:

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;

namespace Copy_From_FTP
{
class Program
{

public static void Main(string[] args)
{
List<FileName> sourceFileList = new List<FileName>();
List<FileName> targetFileList = new List<FileName>();

//string targetURI = ftp://www.target.com
//string targetUser = userName
//string targetPass = passWord
//string sourceURI = ftp://www.source.com
//string sourceUser = userName
//string sourcePass = passWord

getFileLists(sourceURI, sourceUser, sourcePass, sourceFileList, targetURI, targetUser, targetPass, targetFileList);

Console.WriteLine(sourceFileList.Count + " files found!");

CheckLists(sourceFileList, targetFileList);
targetFileList.Sort();

Console.WriteLine(sourceFileList.Count + " unique files on sourceURI"+Environment.NewLine+"Attempting to move them.");

foreach(var file in sourceFileList)
{
try
{
CopyFile(file.fName, sourceURI, sourceUser, sourcePass, targetURI, targetUser, targetPass);
}
catch
{
Console.WriteLine("There was move error with : "+file.fName);
}
}
}

public class FileName : IComparable<FileName>
{
public string fName { get; set; }
public int CompareTo(FileName other)
{
return fName.CompareTo(other.fName);
}
}

public static void CheckLists(List<FileName> sourceFileList, List<FileName> targetFileList)
{
for (int i = 0; i < sourceFileList.Count;i++ )
{
if (targetFileList.BinarySearch(sourceFileList[i]) > 0)
{
sourceFileList.RemoveAt(i);
i--;
}
}
}

public static void getFileLists(string sourceURI, string sourceUser, string sourcePass, List<FileName> sourceFileList,string targetURI, string targetUser, string targetPass, List<FileName> targetFileList)
{
string line = "";
/////////Source FileList
FtpWebRequest sourceRequest;
sourceRequest = (FtpWebRequest)WebRequest.Create(sourceURI);
sourceRequest.Credentials = new NetworkCredential(sourceUser, sourcePass);
sourceRequest.Method = WebRequestMethods.Ftp.ListDirectory;
sourceRequest.UseBinary = true;
sourceRequest.KeepAlive = false;
sourceRequest.Timeout = -1;
sourceRequest.UsePassive = true;
FtpWebResponse sourceRespone = (FtpWebResponse)sourceRequest.GetResponse();
//Creates a list(fileList) of the file names
using (Stream responseStream = sourceRespone.GetResponseStream())
{
using (StreamReader reader = new StreamReader(responseStream))
{
line = reader.ReadLine();
while (line != null)
{
var fileName = new FileName
{
fName = line
};
sourceFileList.Add(fileName);
line = reader.ReadLine();
}
}
}
/////////////Target FileList
FtpWebRequest targetRequest;
targetRequest = (FtpWebRequest)WebRequest.Create(targetURI);
targetRequest.Credentials = new NetworkCredential(targetUser, targetPass);
targetRequest.Method = WebRequestMethods.Ftp.ListDirectory;
targetRequest.UseBinary = true;
targetRequest.KeepAlive = false;
targetRequest.Timeout = -1;
targetRequest.UsePassive = true;
FtpWebResponse targetResponse = (FtpWebResponse)targetRequest.GetResponse();
//Creates a list(fileList) of the file names
using (Stream responseStream = targetResponse.GetResponseStream())
{
using (StreamReader reader = new StreamReader(responseStream))
{
line = reader.ReadLine();
while (line != null)
{
var fileName = new FileName
{
fName = line
};
targetFileList.Add(fileName);
line = reader.ReadLine();
}
}
}
}

public static void CopyFile(string fileName, string sourceURI, string sourceUser, string sourcePass,string targetURI, string targetUser, string targetPass )
{
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(sourceURI + fileName);
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = new NetworkCredential(sourceUser, sourcePass);
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
Upload(fileName, ToByteArray(responseStream),targetURI,targetUser, targetPass);
responseStream.Close();
}
catch
{
Console.WriteLine("There was an error with :" + fileName);
}
}

public static Byte[] ToByteArray(Stream stream)
{
MemoryStream ms = new MemoryStream();
byte[] chunk = new byte[4096];
int bytesRead;
while ((bytesRead = stream.Read(chunk, 0, chunk.Length)) > 0)
{
ms.Write(chunk, 0, bytesRead);
}

return ms.ToArray();
}

public static bool Upload(string FileName, byte[] Image, string targetURI,string targetUser, string targetPass)
{
try
{
FtpWebRequest clsRequest = (FtpWebRequest)WebRequest.Create(targetURI+FileName);
clsRequest.Credentials = new NetworkCredential(targetUser, targetPass);
clsRequest.Method = WebRequestMethods.Ftp.UploadFile;
Stream clsStream = clsRequest.GetRequestStream();
clsStream.Write(Image, 0, Image.Length);
clsStream.Close();
clsStream.Dispose();
return true;
}
catch
{
return false;
}
}
}
}

You may run into issues if you are using things that have special encoding, like text documents. That can be changed by the way the upload function is used. If you're doing text files, use:

 System.Text.Encoding.UTF8.GetBytes(responseStream)

instead of

ToByteArray(responseStream)

You could do a simple extension check of your file before executing the upload.

Upload file to FTP using C#

The existing answers are valid, but why re-invent the wheel and bother with lower level WebRequest types while WebClient already implements FTP uploading neatly:

using (var client = new WebClient())
{
client.Credentials = new NetworkCredential(ftpUsername, ftpPassword);
client.UploadFile("ftp://host/path.zip", WebRequestMethods.Ftp.UploadFile, localFile);
}

C# - How to upload bigger files using FTP?

you should upload the file in 'chunks', not completely. So please try the following:

using (FileStream fileStream = File.OpenRead(filePath))
{
using (Stream reqStream = request.GetRequestStream())
{
long curFileStreamPos = 0;
long chunkSize = 512;

while (curFileStreamPos < fileStream.Length)
{
if (fileStream.Length - curFileStreamPos < chunkSize)
chunkSize = fileStream.Length - curFileStreamPos;

byte[] buff = new byte[chunkSize];
fileStream.Read(buff, 0, buff.Length);
reqStream.Write(buff, 0, buff.Length);

curFileStreamPos += chunkSize;
}

reqStream.Close();
}
fileStream.Close();
}

I have not tested this snippet, so please verify indexes especially.
If you upload a file at once it may happen that the tcp/ip stack does get timeouts due to preparing the data to upload.

Further, this way you do not create big memory objects when you upload files with hundreds of mb (which would end up completely in memory at your solution)



Related Topics



Leave a reply



Submit