Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Monday, August 12, 2019 2:54 AM
I am creating a C# windows form application and I am trying to download files from a remote directory and store them into a local server. However, to make the application more interactive and user friendly, I am looking into adding a progress bar to show the start and finish of the download operation.
This what I am doing to download files from a folder to my device from a remote server. (all the information about host, username etc. are from a JSON file)
private void button6_Click_1(object sender, EventArgs e)
{
//timer1.Enabled = true;
Task.Run(() => Download());
filePath = @"D:\DataProfiler_Nautitech\JSON\app-db.json";
string text = File.ReadAllText(filePath);
var currentList = JsonConvert.DeserializeObject<List<Datalogger>>(text);
//first data
string host = currentList[0].IPaddress;
string username = currentList[0].username;
string password = currentList[0].password;
string remoteDirectory = currentList[0].sourcefolder;
string localDirectory = currentList[0].destfolder;
string filextension = currentList[0].filextension;
using (SftpClient sftp = new SftpClient(host, username, password))
{
try
{
sftp.Connect();
Console.WriteLine("Machine 1 - Connected");
var files = sftp.ListDirectory(remoteDirectory);
foreach (var file in files)
{
try
{
string remoteFileName = file.Name;
if ((file.Name.EndsWith(filextension)))
{
using (Stream file1 = File.OpenWrite(Path.Combine(localDirectory, remoteFileName)))
{
string path = remoteDirectory + "/" + remoteFileName;
sftp.DownloadFile(path, file1);
}
}
}
catch (Exception er1)
{
//MessageBox.Show("An exception has been caught " + er1.ToString());
}
}
}
catch (Exception entry)
{
MessageBox.Show(entry.Message);
}
finally
{
sftp.Disconnect();
}
}
I have looked in some of SSH.NET implementation, and I learned that I have to provide a downloadcallback argument and use a background thread, But this is only done for one file. Here what I have done.
private void button6_Click_1(object sender, EventArgs e)
{
Task.Run(() => Download());
}
private void Download()
{
try
{
filePath = @"D:\DataProfiler_Nautitech\JSON\app-db.json";
string text = File.ReadAllText(filePath);
var currentList = JsonConvert.DeserializeObject<List<Datalogger>>(text);
//first data
string host = currentList[0].IPaddress;
string username = currentList[0].username;
string password = currentList[0].password;
string remoteDirectory = currentList[0].sourcefolder;
string localDirectory = currentList[0].destfolder;
string filextension = currentList[0].filextension;
using (var stream = new FileStream(SourcePath + FileName, FileMode.Create))
using (var client = new SftpClient(host, username, password))
{
client.Connect();
SftpFileAttributes attributes = client.GetAttributes(remoteDirectory+ FileName);
// Set progress bar maximum on foreground thread
progressBar1.Invoke(
(MethodInvoker)delegate { progressBar1.Maximum = (int)attributes.Size; });
// Download with progress callback
client.DownloadFile(RemotePath + FileName, stream, DownloadProgresBar);
MessageBox.Show("Download complete");
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
I need filename to be the files from the directory. But I failed to do so.
I need to download the whole directory with the progress bar show the progression of the operation.
Is there is a way to embed this progress bar with this button.
All replies (6)
Tuesday, August 13, 2019 3:17 AM âś…Answered | 1 vote
Hi samiarja,
Thanks for the feedback.
You could try the following code to show the file download progress bar while downloading the multiple files.
using (var client = new SftpClient(host, username, password))
{
client.Connect();
var files = client.ListDirectory(RemotePath).Select(x=>x.Name);
SftpFileAttributes attributes = null;
FileStream stream = null;
foreach (var item in files)
{
stream = new FileStream(Path.Combine(SourcePath, item), FileMode.Create);
attributes = client.GetAttributes(RemotePath + "/" + item);
progressBar1.Invoke(
(MethodInvoker)delegate { progressBar1.Maximum = (int)attributes.Size; });
client.DownloadFile(RemotePath + "/" + item, stream, DownloadProgresBar);
}
MessageBox.Show("Download complete");
}
Best Regards,
Jack
MSDN Community Support
Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact [email protected].
Monday, August 12, 2019 7:14 AM
Hi samiarja,
Thank you for posting here.
Based on your description, you want to show the file download progress bar while downloading the file.
I modified some code, you could have a look.
using (var stream = new FileStream(Path.Combine(SourcePath , FileName), FileMode.Create))
using (var client = new SftpClient(host, username,password))
{
client.Connect();
SftpFileAttributes attributes = client.GetAttributes(RemotePath + "/"+FileName);
// Set progress bar maximum on foreground thread
progressBar1.Invoke(
(MethodInvoker)delegate { progressBar1.Maximum = (int)attributes.Size; });
// Download with progress callback
client.DownloadFile(RemotePath + "/" + FileName, stream, DownloadProgresBar);
MessageBox.Show("Download complete");
}
Best Regards,
Jack
MSDN Community Support
Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact [email protected].
Monday, August 12, 2019 10:48 PM
Hi Jack,
Thanks for your solution. However, this works only for one file at a time. I am trying to do multiple files. I tried to this but still didn't work for multiple files.
private void Download()
{
filePath = @"D:\DataProfiler_Nautitech\JSON\app-db.json";
string text = File.ReadAllText(filePath);
var currentList = JsonConvert.DeserializeObject<List<Datalogger>>(text);
//first data
string host = currentList[0].IPaddress;
string username = currentList[0].username;
string password = currentList[0].password;
string remoteDirectory = currentList[0].sourcefolder;
string localDirectory = currentList[0].destfolder;
string filextension = currentList[0].filextension;
//first SFTP
using (SftpClient sftp = new SftpClient(host, username, password))
{
try
{
sftp.Connect();
Console.WriteLine("Machine 1 - Connected");
var files = sftp.ListDirectory(remoteDirectory);
foreach (var file in files)
{
try
{
string remoteFileName = file.Name;
SftpFileAttributes attributes = sftp.GetAttributes(remoteDirectory + "/" + remoteFileName);
if ((file.Name.EndsWith(filextension)) || (file.Name.EndsWith(filextension.ToLower())))
{
using (Stream file1 = File.OpenWrite(Path.Combine(localDirectory, remoteFileName)))
{
progressBar1.Invoke(
(MethodInvoker)delegate { progressBar1.Maximum = (int)attributes.Size; });
// Download with progress callback
sftp.DownloadFile(remoteDirectory + "/" + remoteFileName, file1, downloadCallback: GetDownloadProgresBar());
//MessageBox.Show("Download complete");
//string path = remoteDirectory + "/" + remoteFileName;
//sftp.DownloadFile(path, file1);
}
}
}
catch (Exception er1)
{
//MessageBox.Show("An exception has been caught " + er1.ToString());
}
}
}
catch (Exception entry)
{
MessageBox.Show(entry.Message);
}
Tuesday, August 13, 2019 4:22 AM
Thanks jack, I have tried to integrate your solution to my code by replacing RemotePath by the remote server directory, and SourcePath by the local server directory. Like below
private void button1_Click(object sender, EventArgs e)
{
filePath = @"D:\DataProfiler_Nautitech\JSON\app-db.json";
string text = File.ReadAllText(filePath);
var currentList = JsonConvert.DeserializeObject<List<Datalogger>>(text);
//first data
string host = currentList[0].IPaddress;
string username = currentList[0].username;
string password = currentList[0].password;
string remoteDirectory = currentList[0].sourcefolder;
string localDirectory = currentList[0].destfolder;
string filextension = currentList[0].filextension;
string removedownloaded = currentList[1].removedownloaded.ToString();
//Task.Run(() => Delete());
using (var client = new SftpClient(host, username, password))
{
client.Connect();
var files = client.ListDirectory(remoteDirectory).Select(x => x.Name);
SftpFileAttributes attributes = null;
FileStream stream = null;
foreach (var item in files)
{
stream = new FileStream(Path.Combine(localDirectory, item), FileMode.Create);
attributes = client.GetAttributes(remoteDirectory + "/" + item);
progressBar1.Invoke(
(MethodInvoker)delegate { progressBar1.Maximum = (int)attributes.Size; });
client.DownloadFile(remoteDirectory + "/" + item, stream, DownloadProgresBar);
}
MessageBox.Show("Download complete");
}
}
After running it, I am getting this error in my local directory. I though D drive dosn't have restriction!
System.UnauthorizedAccessException: 'Access to the path 'D:\DataProfiler_Nautitech\Files' is denied.'
Am I doing anything wrong in this code? or should I change to directory path?
Thanks in advance.
Tuesday, August 13, 2019 5:19 AM
Hi samiar,
Thanks for the feedback.
First, I want to tell you that this error does not occur for me.
Second, you could try to check that if any other process are accessing this path, if so, close it.
Third, you could try to create a new directory path to receive the downloaded files.
Best Regards,
Jack
MSDN Community Support
Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact [email protected].
Sunday, August 18, 2019 10:26 PM
Hi Jack,
I assume that the problem is from my side. I will mark your solution as the answer and I will do the required modification to my code to make it work.
Thanks for your help, I appreciate it.