-
-
Notifications
You must be signed in to change notification settings - Fork 933
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
how can i download a directory from a server via SFTP/SCP to a zip file #948
Comments
I made this code below but I don't know if it's the best approach using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ionic.Zip;
using Renci.SshNet;
using Renci.SshNet.Sftp;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var connectionInfo = new ConnectionInfo("192.168.133.13", "user",
new PasswordAuthenticationMethod("isaque.neves", "pass"));
using (var client = new SftpClient(connectionInfo))
{
client.Connect();
DownloadDirectoryAsZip(client,"/var/www/teste", @"C:\MyCsharpProjects\fsbackup\download.zip");
}
Console.WriteLine("end");
}
public static void DownloadDirectoryAsZip(SftpClient sftpClient, string sourceRemotePath, string destLocalPath)
{
ZipFile zip = new ZipFile();
DownloadDirectoryAsZipRec(zip, sftpClient, sourceRemotePath);
zip.Save(destLocalPath);
zip.Dispose();
}
private static void DownloadDirectoryAsZipRec(ZipFile zip,SftpClient sftpClient, string sourceRemotePath)
{
IEnumerable<SftpFile> files = sftpClient.ListDirectory(sourceRemotePath);
foreach (SftpFile file in files)
{
if ((file.Name != ".") && (file.Name != ".."))
{
string sourceFilePath = sourceRemotePath + "/" + file.Name;
if (file.IsDirectory)
{
DownloadDirectoryAsZipRec(zip,sftpClient, sourceFilePath);
}
else
{
var memoryStream = new MemoryStream();
sftpClient.DownloadFile(sourceFilePath, memoryStream);
zip.AddEntry(sourceFilePath, memoryStream);
}
}
}
}
}
}
|
I have two suggestions:
|
@IgorMilavec static void Main(string[] args)
{
var watch = new System.Diagnostics.Stopwatch();
watch.Start();
var connectionInfo = new ConnectionInfo("192.168.2.77", "root",
new PasswordAuthenticationMethod("root", "pass"));
var client = new SftpClient(connectionInfo);
client.Connect();
DownloadDirectoryAsZip2(client, "/var/www/html", @"C:\MyCsharpProjects\fsbackup\download.zip");
client.Dispose();
Console.WriteLine("end Download");
watch.Stop();
Console.WriteLine($"Execution Time: {watch.ElapsedMilliseconds} ms");
}
public static void DownloadDirectoryAsZip2(SftpClient sftpClient, string sourceRemotePath, string destLocalPath)
{
using (var zipFile = new FileStream(destLocalPath, FileMode.OpenOrCreate))
{
using (var archive = new ZipArchive(zipFile, ZipArchiveMode.Update))
{
DownloadDirectoryAsZipRec2(archive, sftpClient, sourceRemotePath);
}
}
}
private static void DownloadDirectoryAsZipRec2(ZipArchive archive, SftpClient sftpClient, string sourceRemotePath)
{
try
{
var files = sftpClient.ListDirectory(sourceRemotePath);
foreach (var file in files)
{
if ((file.Name != ".") && (file.Name != ".."))
{
var sourceFilePath = sourceRemotePath + "/" + file.Name;
if (file.IsDirectory)
{
DownloadDirectoryAsZipRec2(archive, sftpClient, sourceFilePath);
}
else
{
ZipArchiveEntry entry = archive.CreateEntry(sourceFilePath);
using (Stream stream = entry.Open()) {
try
{
sftpClient.DownloadFile(sourceFilePath, stream);
}
catch (Exception e)
{
Console.WriteLine($"Download File failed: {sourceFilePath} | Error:{e}");
}
}
}
}
}
}catch (Exception e)
{
Console.WriteLine($"Download Directory failed: {sourceRemotePath} | Error:{e}");
}
}
} |
Your code looks OK at first glance. |
@IgorMilavec Is there a convenient and easy way to show directory download progress with SSH.NET? It would be nice if SSH.NET already provides the download directory to zip with a progress callback. |
You can provide a callback to |
@IgorMilavec ///return total size in bytes of Directory
int getSizeOfDirectory(
Pointer<ssh_session_struct> session, String remoteDirectoryPath,
{bool isThrowException = true}) {
var cmdToGetTotaSize =
"find $remoteDirectoryPath -type f -print0 | xargs -0 stat --format=%s | awk '{s+=\$1} END {print s}'";
String? cmdRes;
try {
cmdRes = execCommandSync(session, cmdToGetTotaSize);
if (cmdRes.trim().isEmpty) {
//check is symbolic link
cmdRes = execCommandSync(session, 'file $remoteDirectoryPath');
//is it a symbolic link?
if (cmdRes.contains('symbolic')) {
// get the real path of the symbolic link
var cmdRe =
execCommandSync(session, 'readlink -f $remoteDirectoryPath');
if (cmdRe.trim().isNotEmpty) {
cmdRes = execCommandSync(session,
"find ${cmdRe.replaceAll(RegExp(r'\n'), '')} -type f -print0 | xargs -0 stat --format=%s | awk '{s+=\$1} END {print s}'");
}
}
}
//for old debian like debian 6
//old debian bug 1.57903e+10
if (cmdRes.contains('e+')) {
cmdRes = execCommandSync(session,
'find $remoteDirectoryPath -type f -print0 | xargs -0 stat --format=%s | paste -sd+ - | bc -l');
} else if (int.tryParse(cmdRes) == null) {
cmdRes = execCommandSync(session,
'find $remoteDirectoryPath -type f -print0 | du -scb -L --apparent-size --files0-from=- | tail -n 1');
return int.parse(cmdRes.split(' ').first.trim());
}
return int.parse(cmdRes);
} catch (e) {
print(
'getSizeOfDirectory: $e \r\n cmdToGetTotaSize: $cmdToGetTotaSize \r\n cmdRes: $cmdRes');
if (isThrowException) {
throw LibsshGetFileSizeException(
'Unable to get the size of a directory in bytes, \r\n cmd: $cmdToGetTotaSize cmdResult: $cmdRes');
}
}
return 0;
} code from libssh_binding |
I don't know how to do this using SSH.NET
I already did it in rust, but I don't know how to do it using SSH.NET
The text was updated successfully, but these errors were encountered: