How to copy a file on an FTP server? - c#

How do you copy a file on an FTP server? My goal is to copy ftp://www.mysite.com/test.jpg to ftp://www.mysite.com/testcopy.jpg. To rename a file, I would use:
var request = (FtpWebRequest)WebRequest.Create("ftp://www.mysite.com/test.jpg");
request.Credentials = new NetworkCredential(user, pass);
request.Method = WebRequestMethods.Ftp.Rename;
request.RenameTo = "testrename.jpg"
request.GetResponse().Close();
FtpWebResponse resp = (FtpWebResponse)request.GetResponse();
However, there is no Method for copying files. How would you do copy a file?

Try this:
static void Main(string[] args)
{
CopyFile("countrylist.csv", "MySample.csv", "username", "password#");
}
public static bool CopyFile(string fileName, string FileToCopy, string userName, string password)
{
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://ftp.mysite.net/" + fileName);
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = new NetworkCredential(userName, password);
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
Upload("ftp://ftp.mysite.net/" + FileToCopy, ToByteArray(responseStream), userName, password);
responseStream.Close();
return true;
}
catch
{
return false;
}
}
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 FtpUsername, string FtpPassword)
{
try
{
System.Net.FtpWebRequest clsRequest = (System.Net.FtpWebRequest)System.Net.WebRequest.Create(FileName);
clsRequest.Credentials = new System.Net.NetworkCredential(FtpUsername, FtpPassword);
clsRequest.Method = System.Net.WebRequestMethods.Ftp.UploadFile;
System.IO.Stream clsStream = clsRequest.GetRequestStream();
clsStream.Write(Image, 0, Image.Length);
clsStream.Close();
clsStream.Dispose();
return true;
}
catch
{
return false;
}
}
This downloads the file to a stream, and then uploads it.

FtpWebRequest is a lightweight class. Microsoft felt it should be used by simple client to download and delete the files once the client is finish.

I guess you can't really do this with FTP. What you can do is download the file you want to copy and then upload it with a new name. For example:
try
{
WebClient request = new WebClient();
request.Credentials = new NetworkCredential(user, pass);
byte[] data = request.DownloadData(host);
MemoryStream file = new MemoryStream(data);
Upload(data);
}
catch (Exception ex)
{
}
...
private void Upload(byte[] buffer)
{
try
{
FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(newname);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(user, pass);
Stream reqStream = request.GetRequestStream();
reqStream.Write(buffer, 0, buffer.Length);
reqStream.Close();
var resp = (FtpWebResponse)request.GetResponse();
}
catch (Exception ex)
{
}
}

In our project we did someting like this
// pass parameters according to your need,
// the below code is done in a hard coded manner for clarity
public void Copy()
{
// from where you want to copy
var downloadRequest = (FtpWebRequest)WebRequest.Create("ftp://www.mysite.com/test.jpg");
downloadRequest.Credentials = new NetworkCredential("userName", "passWord");
downloadRequest.Method = WebRequestMethods.Ftp.DownloadFile;
var ftpWebResponse = (FtpWebResponse)downloadRequest.GetResponse();
var downloadResponse = ftpWebResponse.GetResponseStream();
int buffLength = 2048;
byte[] byteBuffer = new byte[buffLength];
// bytes read from download stream.
// from documentation: When overridden in a derived class, reads a sequence of bytes from the
// current stream and advances the position within the stream by the number of bytes read.
int bytesRead = downloadResponse.Read(byteBuffer, 0, buffLength);
// the place where you want the file to go
var uploadRequest = (FtpWebRequest)WebRequest.Create("ftp://www.mysite.com/testCopy.jpg");
uploadRequest.Credentials = new NetworkCredential("userName", "passWord");
uploadRequest.Method = WebRequestMethods.Ftp.UploadFile;
var uploadStream = uploadRequest.GetRequestStream();
if (bytesRead > 0)
{
while (bytesRead > 0)
{
uploadStream.Write(byteBuffer, 0, bytesRead);
bytesRead = downloadResponse.Read(byteBuffer, 0, buffLength);
}
}
uploadStream.Close();
uploadStream.Dispose();
downloadResponse.Close();
ftpWebResponse.Close();
((IDisposable)ftpWebResponse).Dispose();
}

Related

Upload a .txt file to a website page from a C# win forms app [duplicate]

I try upload a file to an FTP-server with C#. The file is uploaded but with zero bytes.
private void button2_Click(object sender, EventArgs e)
{
var dirPath = #"C:/Documents and Settings/sander.GD/Bureaublad/test/";
ftp ftpClient = new ftp("ftp://example.com/", "username", "password");
string[] files = Directory.GetFiles(dirPath,"*.*");
var uploadPath = "/httpdocs/album";
foreach (string file in files)
{
ftpClient.createDirectory("/test");
ftpClient.upload(uploadPath + "/" + Path.GetFileName(file), file);
}
if (string.IsNullOrEmpty(txtnaam.Text))
{
MessageBox.Show("Gelieve uw naam in te geven !");
}
}
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);
}
Easiest way
The most trivial way to upload a file to an FTP server using .NET framework is using WebClient.UploadFile method:
WebClient client = new WebClient();
client.Credentials = new NetworkCredential("username", "password");
var url = "ftp://ftp.example.com/remote/path/file.zip";
client.UploadFile(url, #"C:\local\path\file.zip");
Advanced options
If you need a greater control, that WebClient does not offer (like TLS/SSL encryption, ascii/text transfer mode, active mode, transfer resuming, progress monitoring, etc), use FtpWebRequest. Easy way is to just copy a FileStream to an FTP stream using Stream.CopyTo:
var url = "ftp://ftp.example.com/remote/path/file.zip";
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
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);
}
Progress monitoring
If you need to monitor an upload progress, you have to copy the contents by chunks yourself:
var url = "ftp://ftp.example.com/remote/path/file.zip";
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
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 C# example at:
How can we show progress bar for upload with FtpWebRequest
Uploading folder
If you want to upload all files from a folder, see
Upload directory of files to FTP server using WebClient.
For a recursive upload, see
Recursive upload to FTP server in C#
.NET 5 Guide
async Task<FtpStatusCode> FtpFileUploadAsync(string ftpUrl, string userName, string password, string filePath)
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpUrl);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(userName, password);
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
using (Stream requestStream = request.GetRequestStream())
{
await fileStream.CopyToAsync(requestStream);
}
using (FtpWebResponse response = (FtpWebResponse)await request.GetResponseAsync())
{
return response.StatusCode;
}
}
.NET Framework
public void UploadFtpFile(string folderName, string fileName)
{
FtpWebRequest request;
string folderName;
string fileName;
string absoluteFileName = Path.GetFileName(fileName);
request = WebRequest.Create(new Uri(string.Format(#"ftp://{0}/{1}/{2}", "127.0.0.1", folderName, absoluteFileName))) as FtpWebRequest;
request.Method = WebRequestMethods.Ftp.UploadFile;
request.UseBinary = 1;
request.UsePassive = 1;
request.KeepAlive = 1;
request.Credentials = new NetworkCredential(user, pass);
request.ConnectionGroupName = "group";
using (FileStream fs = File.OpenRead(fileName))
{
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
fs.Close();
Stream requestStream = request.GetRequestStream();
requestStream.Write(buffer, 0, buffer.Length);
requestStream.Flush();
requestStream.Close();
}
}
How to use
UploadFtpFile("testFolder", "E:\\filesToUpload\\test.img");
use this in your foreach
and you only need to create folder one time
to create a folder
request = WebRequest.Create(new Uri(string.Format(#"ftp://{0}/{1}/", "127.0.0.1", "testFolder"))) as FtpWebRequest;
request.Method = WebRequestMethods.Ftp.MakeDirectory;
FtpWebResponse ftpResponse = (FtpWebResponse)request.GetResponse();
The following works for me:
public virtual void Send(string fileName, byte[] file)
{
ByteArrayToFile(fileName, file);
var request = (FtpWebRequest) WebRequest.Create(new Uri(ServerUrl + fileName));
request.Method = WebRequestMethods.Ftp.UploadFile;
request.UsePassive = false;
request.Credentials = new NetworkCredential(UserName, Password);
request.ContentLength = file.Length;
var requestStream = request.GetRequestStream();
requestStream.Write(file, 0, file.Length);
requestStream.Close();
var response = (FtpWebResponse) request.GetResponse();
if (response != null)
response.Close();
}
You can't read send the file parameter in your code as it is only the filename.
Use the following:
byte[] bytes = File.ReadAllBytes(dir + file);
To get the file so you can pass it to the Send method.
public static void UploadFileToFtp(string url, string filePath, string username, string password)
{
var fileName = Path.GetFileName(filePath);
var request = (FtpWebRequest)WebRequest.Create(url + fileName);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(username, password);
request.UsePassive = true;
request.UseBinary = true;
request.KeepAlive = false;
using (var fileStream = File.OpenRead(filePath))
{
using (var requestStream = request.GetRequestStream())
{
fileStream.CopyTo(requestStream);
requestStream.Close();
}
}
var response = (FtpWebResponse)request.GetResponse();
Console.WriteLine("Upload done: {0}", response.StatusDescription);
response.Close();
}
In the first example must change those to:
requestStream.Flush();
requestStream.Close();
First flush and after that close.
This works for me,this method will SFTP a file to a location within your network.
It uses SSH.NET.2013.4.7 library.One can just download it for free.
//Secure FTP
public void SecureFTPUploadFile(string destinationHost,int port,string username,string password,string source,string destination)
{
ConnectionInfo ConnNfo = new ConnectionInfo(destinationHost, port, username, new PasswordAuthenticationMethod(username, password));
var temp = destination.Split('/');
string destinationFileName = temp[temp.Count() - 1];
string parentDirectory = destination.Remove(destination.Length - (destinationFileName.Length + 1), destinationFileName.Length + 1);
using (var sshclient = new SshClient(ConnNfo))
{
sshclient.Connect();
using (var cmd = sshclient.CreateCommand("mkdir -p " + parentDirectory + " && chmod +rw " + parentDirectory))
{
cmd.Execute();
}
sshclient.Disconnect();
}
using (var sftp = new SftpClient(ConnNfo))
{
sftp.Connect();
sftp.ChangeDirectory(parentDirectory);
using (var uplfileStream = System.IO.File.OpenRead(source))
{
sftp.UploadFile(uplfileStream, destinationFileName, true);
}
sftp.Disconnect();
}
}
publish date: 06/26/2018
https://learn.microsoft.com/en-us/dotnet/framework/network-programming/how-to-upload-files-with-ftp
using System;
using System.IO;
using System.Net;
using System.Text;
namespace Examples.System.Net
{
public class WebRequestGetExample
{
public static void Main ()
{
// Get the object used to communicate with the server.
FtpWebRequest request =
(FtpWebRequest)WebRequest.Create("ftp://www.contoso.com/test.htm");
request.Method = WebRequestMethods.Ftp.UploadFile;
// This example assumes the FTP site uses anonymous logon.
request.Credentials = new NetworkCredential("anonymous",
"janeDoe#contoso.com");
// Copy the contents of the file to the request stream.
byte[] fileContents;
using (StreamReader sourceStream = new StreamReader("testfile.txt"))
{
fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
}
request.ContentLength = fileContents.Length;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(fileContents, 0, fileContents.Length);
}
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
{
Console.WriteLine($"Upload File Complete, status
{response.StatusDescription}");
}
}
}
}
Best way I've found is FluentFtp
You can find the repo here:
https://github.com/robinrodricks/FluentFTP
and the quickstart example here:
https://github.com/robinrodricks/FluentFTP/wiki/Quick-Start-Example.
And actually the WebRequest class recommended by a few people here, is not recommended by Microsoft anymore, check out this page:
https://learn.microsoft.com/en-us/dotnet/api/system.net.webrequest?view=net-5.0
// create an FTP client and specify the host, username and password
// (delete the credentials to use the "anonymous" account)
FtpClient client = new FtpClient("123.123.123.123", "david", "pass123");
// connect to the server and automatically detect working FTP settings
client.AutoConnect();
// upload a file and retry 3 times before giving up
client.RetryAttempts = 3;
client.UploadFile(#"C:\MyVideo.mp4", "/htdocs/big.txt",
FtpRemoteExists.Overwrite, false, FtpVerify.Retry);
// disconnect! good bye!
client.Disconnect();
I have observed that -
FtpwebRequest is missing.
As the target is FTP, so the NetworkCredential required.
I have prepared a method that works like this, you can replace the value of the variable ftpurl with the parameter TargetDestinationPath. I had tested this method on winforms application :
private void UploadProfileImage(string TargetFileName, string TargetDestinationPath, string FiletoUpload)
{
//Get the Image Destination path
string imageName = TargetFileName; //you can comment this
string imgPath = TargetDestinationPath;
string ftpurl = "ftp://downloads.abc.com/downloads.abc.com/MobileApps/SystemImages/ProfileImages/" + imgPath;
string ftpusername = krayknot_DAL.clsGlobal.FTPUsername;
string ftppassword = krayknot_DAL.clsGlobal.FTPPassword;
string fileurl = FiletoUpload;
FtpWebRequest ftpClient = (FtpWebRequest)FtpWebRequest.Create(ftpurl);
ftpClient.Credentials = new System.Net.NetworkCredential(ftpusername, ftppassword);
ftpClient.Method = System.Net.WebRequestMethods.Ftp.UploadFile;
ftpClient.UseBinary = true;
ftpClient.KeepAlive = true;
System.IO.FileInfo fi = new System.IO.FileInfo(fileurl);
ftpClient.ContentLength = fi.Length;
byte[] buffer = new byte[4097];
int bytes = 0;
int total_bytes = (int)fi.Length;
System.IO.FileStream fs = fi.OpenRead();
System.IO.Stream rs = ftpClient.GetRequestStream();
while (total_bytes > 0)
{
bytes = fs.Read(buffer, 0, buffer.Length);
rs.Write(buffer, 0, bytes);
total_bytes = total_bytes - bytes;
}
//fs.Flush();
fs.Close();
rs.Close();
FtpWebResponse uploadResponse = (FtpWebResponse)ftpClient.GetResponse();
string value = uploadResponse.StatusDescription;
uploadResponse.Close();
}
Let me know in case of any issue, or here is one more link that can help you:
https://msdn.microsoft.com/en-us/library/ms229715(v=vs.110).aspx

C # Upload all files in a folder on the PC to an FTP folder

As I can upload all .txt files from one folder to an FTP folder. I can upload only one file but I need to upload all the files that are inside a folder on your computer to an FTP folder
FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create("ftp://123.456.789.00/folder1/folder2" + "/" + Path.GetFileName("D:\\folderUpload\\1test.txt"));
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential("username", "pass");
request.UsePassive = true;
request.UseBinary = true;
request.KeepAlive = false;
FileStream stream = File.OpenRead("D:\\folderUpload\\1test.txt");
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
stream.Close();
Stream reqStream = request.GetRequestStream();
reqStream.Write(buffer, 0, buffer.Length);
reqStream.Close();
MessageBox.Show("Upload OK");
Tou can do something like that (it can be improved if you want to keep the original tree or parallelize...):
static public void Main(string[] args)
{
DirectoryInfo directory = DirectoryInfo(#"C:\PathToUpload");
foreach(var file in directory.GetFiles(*)){
UploadFile(file, "ftp://123.456.789.00/folder1/folder2");
}
MessageBox.Show("Upload OK");
}
public void UploadFile(FileInfo file,string ftpUrl){
FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(ftpUrl + "/" + file.Name);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential("username", "pass");
request.UsePassive = true;
request.UseBinary = true;
request.KeepAlive = false;
FileStream stream = File.OpenRead("D:\\folderUpload\\1test.txt");
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
stream.Close();
Stream reqStream = request.GetRequestStream();
reqStream.Write(buffer, 0, buffer.Length);
reqStream.Close();
}
public static void uploadFolder(string source, string uploadpath)
{
WebRequest request = WebRequest.Create(uploadpath);
request.Credentials = new NetworkCredential(userName, password);
string[] files = Directory.GetFiles(source, "*.*");
string[] subFolders = Directory.GetDirectories(source);
foreach(string file in files)
{
request = WebRequest.Create(file);
request.Method = WebRequestMethods.Ftp.UploadFile;
}
foreach(string subFolder in subFolders)
{
request = WebRequest.Create(uploadpath + "/"+ Path.GetFileName(subFolder));
request.Method = WebRequestMethods.Ftp.MakeDirectory; <br/>
request.Credentials = new NetworkCredential(userName,password);
uploadFolder(subFolder, uploadpath+"/"+Path.GetFileName(subFolder));
}
}

How to store richtextbox content directly to ftp in C#?

Guys this the code to store file on ftp. Can any one reconfigure this code so that it stores the contents of the richtextbox in windows forms I'm writing anything on richtextbox when I click button it should store directly ftp.
{
Stream requestStream = null;
FileStream fileStream = null;
FtpWebResponse uploadResponse = null;
try
{
uploadUrl = "ftp://ftp.personalwebars.com/ATM/";
fileName = txtTitle.Text + ".txt";
FtpWebRequest uploadRequest = (FtpWebRequest)WebRequest.Create(uploadUrl + #"/" + fileName);
uploadRequest.Method = WebRequestMethods.Ftp.UploadFile;
//Since the FTP you are downloading to is secure, send
//in user name and password to be able upload the file
ICredentials credentials = new NetworkCredential(user, pswd);
uploadRequest.Credentials = credentials;
//UploadFile is not supported through an Http proxy
//so we disable the proxy for this request.
uploadRequest.Proxy = null;
//uploadRequest.UsePassive = false; <--found from another forum and did not make a difference
requestStream = uploadRequest.GetRequestStream();
byte[] buffer = new byte[1024];
int bytesRead;
while (true)
{
bytesRead = fileStream.Read(buffer, 0, buffer.Length);
if (bytesRead == 0)
break;
requestStream.Write(buffer, 0, bytesRead);
}
//The request stream must be closed before getting
//the response.
requestStream.Close();
uploadResponse =
(FtpWebResponse)uploadRequest.GetResponse();
lblAuthentication.Text = "Your solution has been submitted in txt Mode. Thank You";
}
catch (WebException ex)
{
}
finally
{
if (uploadResponse != null)
uploadResponse.Close();
if (fileStream != null)
fileStream.Close();
if (requestStream != null)
requestStream.Close();
}
}
Try this, extract the string from the text box and pass it in as the content parameter,
public void Send(string url, string fileName, string content, string user, string password)
{
byte[] bytes = Encoding.ASCII.GetBytes(content)
var request = (FtpWebRequest) WebRequest.Create(new Uri(url + #"/" + fileName));
request.Method = WebRequestMethods.Ftp.UploadFile;
request.UsePassive = false;
request.Credentials = new NetworkCredential(user, password);
request.ContentLength = bytes.Length;
var requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
var response = (FtpWebResponse) request.GetResponse();
if (response != null) response.Close();
}

Uploading two times a file to FTP

I need to upload the same file (attached by the way to a WebForm) to an FTP server in two different directories.
The problem is that the first upload is OK, but the second is not OK - the file is missing or if present has 0 length (is empty)..
Here is my code (my FtpManager class):
public void UploadFile(HttpPostedFileBase fileToUpload, string ftpDirPath)
{
try
{
var uploadUrl = string.Format("ftp://{0}//{1}", serverIp, ftpDirPath);
var uploadFilename = fileToUpload.FileName;
Stream streamObj = fileToUpload.InputStream;
byte[] buffer = new byte[fileToUpload.ContentLength];
streamObj.Read(buffer, 0, buffer.Length);
streamObj.Close();
streamObj = null;
string ftpurl = String.Format("{0}/{1}", uploadUrl, uploadFilename);
ftpRequest = FtpWebRequest.Create(ftpurl) as FtpWebRequest;
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
ftpRequest.Timeout = 1000000;
ftpRequest.UseBinary = true;
ftpRequest.UsePassive = true;
ftpRequest.KeepAlive = true;
ftpRequest.Credentials = new NetworkCredential(username, password);
Stream requestStream = ftpRequest.GetRequestStream();
requestStream.Write(buffer, 0, buffer.Length);
requestStream.Flush();
requestStream.Close();
requestStream = null;
FtpWebResponse uploadResponse = (FtpWebResponse)ftpRequest.GetResponse();
uploadResponse.Close();
ftpRequest = null;
}
catch
{
throw;
}
}
I use it like this:
string serverIp = SERVER;
string user = FTP_USER;
string pass = FTP_PASSWORD;
string ftpDir1 = "var/www/rrhh/_lib/tmp";
string ftpDir2 = "var/www/rrhh/docs";
var ftpManager = new FtpManager(serverIp, user, pass);
ftpManager.UploadFile(file, ftpDir1);
ftpManager.UploadFile(file, ftpDir2);
So my question is my the second time my method works (does not throw exceptions), but however does not (upload correctly the file)?
PS.
Analysing the result:
FtpWebResponse uploadResponse = (FtpWebResponse)ftpRequest.GetResponse();
response = "Status Code: {0}; Description: {1}".Fill(
uploadResponse.StatusCode,
uploadResponse.StatusDescription);
uploadResponse.Close();
First Upload
Status Code: ClosingData; Description: 226 File receive OK.
Second Upload:
Status Code: ClosingData; Description: 226 File receive OK.
After reading from your InputStream, you are at its end and the second time you get an empty byte array. Use streamObj.Position = 0 before the call to streamObj.Read() to go back to the start of the InputStream.
Might I suggest saving the file to a temporary directory, eg. using:
var fileName = System.IO.Path.GetTempFileName();
file.SaveAs(fileName);
[...]
ftpManager.UploadFile(fileName, ftpDir1);
ftpManager.UploadFile(fileName, ftpDir2);
System.IO.File.Delete(fileName);
Then change your UploadFile method to use a filename instead:
public void UploadFile(string fileToUpload, string ftpDirPath)
[...]
Stream streamObj = File.OpenRead(fileToUpload);
byte[] buffer = new byte[streamObj.Length];
[...]
Modified like this (added bool closeStream):
public void UploadFile(HttpPostedFileBase fileToUpload,
string ftpDirPath, bool closeStream)
{
try
{
var uploadFilename = fileToUpload.FileName;
Stream streamObj = fileToUpload.InputStream;
byte[] buffer = new byte[fileToUpload.ContentLength];
streamObj.Position = 0;
streamObj.Read(buffer, 0, buffer.Length);
if (closeStream)
{
streamObj.Close();
streamObj = null;
}
...
usage:
ftpManager.UploadFile(file, ftpDir1, false);
ftpManager.UploadFile(file, ftpDir2, true);

How to download FTP files with automatic resume in case of disconnect

I can download FTP files, but the download code does not have a resume facility and multi part files download. Because there are file larger than 500 MB, I can't download them continuously, because the connection gets closed and it starts download from beginning. I wanted my code a resume facility if it gets disconnected.
The code I am using is:
public string[] GetFileList()
{
string[] downloadFiles;
StringBuilder result = new StringBuilder();
FtpWebRequest reqFTP;
try
{
reqFTP = (FtpWebRequest)FtpWebRequest.Create(
new Uri("ftp://" + ftpServerIP + "/"));
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
reqFTP.Method = WebRequestMethods.Ftp.ListDirectory;
WebResponse response = reqFTP.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
//MessageBox.Show(reader.ReadToEnd());
string line = reader.ReadLine();
while (line != null)
{
result.Append(line);
result.Append("\n");
line = reader.ReadLine();
}
result.Remove(result.ToString().LastIndexOf('\n'), 1);
reader.Close();
response.Close();
//MessageBox.Show(response.StatusDescription);
return result.ToString().Split('\n');
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
downloadFiles = null;
return downloadFiles;
}
}
private void Download(string filePath, string fileName)
{
FtpWebRequest reqFTP;
try
{
//filePath = <<The full path where the file is to be created.>>,
//fileName = <<Name of the file to be created
// (Need not be the name of the file on FTP server).>>
FileStream outputStream =
new FileStream(filePath + "\\" + fileName, FileMode.Create);
reqFTP = (FtpWebRequest)FtpWebRequest.Create(
new Uri("ftp://" + ftpServerIP + "/" + fileName));
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream ftpStream = response.GetResponseStream();
long cl = response.ContentLength;
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[bufferSize];
readCount = ftpStream.Read(buffer, 0, bufferSize);
while (readCount > 0)
{
outputStream.Write(buffer, 0, readCount);
readCount = ftpStream.Read(buffer, 0, bufferSize);
}
ftpStream.Close();
outputStream.Close();
response.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Before you start downloading check for the existence of the file on the local filesystem. If it exists, then get the size and use that for the ContentOffset member of the FtpWebRequest object. This functionality may not be supported by the FTP server, though.
A native implementation of FTP download resumption using the FtpWebRequest:
bool resume = false;
do
{
try
{
FileMode mode = resume ? FileMode.Append : FileMode.Create;
resume = false;
using (Stream fileStream = File.Open(#"C:\local\path\file.dat", mode))
{
var url = "ftp://ftp.example.com/remote/path/file.dat";
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.ContentOffset = fileStream.Position;
using (Stream ftpStream = request.GetResponse().GetResponseStream())
{
ftpStream.CopyTo(fileStream);
}
}
}
catch (WebException)
{
resume = true;
}
}
while (resume);
Or use an FTP library that can resume the transfer automatically.
For example WinSCP .NET assembly does. With it, a resumable download is as trivial as:
// Setup session options
var sessionOptions = new WinSCP.SessionOptions
{
Protocol = Protocol.Ftp,
HostName = "ftp.example.com",
UserName = "user",
Password = "mypassword"
};
using (var session = new Session())
{
// Connect
session.Open(sessionOptions);
// Resumable download
session.GetFileToDirectory("/home/user/file.zip", #"C:\path");
}
(I'm the author of WinSCP)

Categories

Resources