Upload File and Download File from Ftp

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.

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.

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 FTP and upload it again

Some links:

VB.NET: http://www.codeproject.com/KB/IP/FtpClient.aspx

c#: http://www.c-sharpcorner.com/uploadfile/neo_matrix/simpleftp01172007082222am/simpleftp.aspx

Download file from ftp server while file is yet being uploaded

I created the following automated solution based on inputs from answers at this post and others too, to address my problem as it is, meaning: Pull files from different FTP servers, from different brands,in a scenario where concurrency is much like to happen.

Using signal files or other mechanisms suggest in this post would require force clients to change the way they interact with us, so it is a solution for most cases but not a solution for my particular problem.

So, my solution was:

  1. scan the folder parsing filename, data and size of each file.
  2. discard any file that is too new. Only if file date is older than a few minutes it is considered for download. Hangs may cause this rule to fail preventing concurrency.
  3. Rename the file. It it fails, jump out. This method, based on concurrency, has proven to be 100% accurate so far.
  4. download the renamed file.
  5. check size of transfer and see if match the size attribute (paranoia check)
  6. delete the successful transferred file from the ftp server.

This solution allow us to poll ftp folders intensively.

Node FTP download files from one server and upload to another server

So I found a solution. In my getAndInsert() function was doing:

c.get(file.path + '/' + file.name, function(err, stream) {
if (err) {console.log(err); console.log("FILE NAME: " + file.name)}
d.put(stream.pipe(passThrough()), '/images/' + file.name, function() {
_this.uploadCount += 1;
_this.uploadedImages.push(file.name)
console.log(_this.uploadCount + '/' + _this._list.length + " uploaded.")
c.end();
d.end();
resolve(true);
});
});

The problem resided in stream.pipe(passThrough()). It seemed as if I was trying to write after the stream had already ended. This is what solved my problem:

let chunks = [];
stream.on('data', (chunk) => {
chunks.push(chunk);
})
stream.on('end', () => {
d.put(Buffer.concat(chunks), '/images/' + file.name, function() {
_this.uploadCount += 1;
_this.uploadedImages.push(file.name)
console.log(_this.uploadCount + '/' + _this._list.length + " uploaded.")
c.end();
d.end();
resolve(true);
});
})

When new data is available from the stream push to an array called chunks. When the stream is finished, call .put and pass in Buffer.concat(chunks)

Hope this helps anyone going through a similar problem.



Related Topics



Leave a reply



Submit