Connect SFTP server using x++.
For this, we need to create a C# project and we need to write code in C#. After that DLL file, I need to add it as a reference for my D365 project.
We need to download Renci.ssh.Net from the NuGet package.
We can download SSH from the below link:
https://github.com/sshnet/SSH.NET/releases/tag/2020.0.1
or
https://www.dllme.com./dll/files/renci_sshnet
Please follow this blog for Renci. Link
C# Code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Renci.SshNet;
namespace SFTPConnect
{
public class sftpConnection
{
public SftpClient sftpClient;
public SftpClient OpenSFTPConnection(string host, int port, string username, string password)
{
if (this.sftpClient == null)
{
this.sftpClient = new Renci.SshNet.SftpClient(host, port, username, password);
--------------or-------------------------
List<AuthenticationMethod> methods = new List<AuthenticationMethod>
{
new PasswordAuthenticationMethod(username, password)
};
var connectionInfo = new ConnectionInfo(host, port, username, methods.ToArray());
this.sftpClient = new SftpClient(connectionInfo);
}
if (!this.sftpClient.IsConnected)
{
this.sftpClient.Connect();
}
return this.sftpClient;
}
public List<string> GetDirectories(SftpClient _SftpClient, string path)
{
return _SftpClient.ListDirectory(path)/*.Where(n => n.IsDirectory)*/.Select(n => n.Name).ToList();
}
public void MoveFile(SftpClient _SftpClient, string sourcePath, string destinationPath, bool isPosix)
{
_SftpClient.RenameFile(sourcePath, destinationPath, isPosix);
}
public Stream DownloadFile(SftpClient _SftpClient, string sourcePath)
{
var memoryStream = new MemoryStream();
_SftpClient.DownloadFile(sourcePath, memoryStream);
memoryStream.Position = 0;
return memoryStream;
}
public void upLoadFile(SftpClient _SftpClient, System.IO.Stream _sourceFile, string _fileName)
{
_sourceFile.Position = 0;
_SftpClient.BufferSize = 8 * 1024;
_SftpClient.UploadFile(_sourceFile, _fileName);
}
}
}
X++ Code:
public void sFTPConnection()
{
str sftpFile;
ClrObject list = new ClrObject("System.Collections.Generic.List`1[System.String]");
SFTPConnect.sftpConnection sftp = new SFTPConnect.sftpConnection();
using (var sftpConnection = sftp.OpenSFTPConnection(host, port, username, password)) // Connect
{
try
{
int totalFiles = 0;
sftpConnection.ChangeDirectory('/Upload');//Import Path
list = (sftp.GetDirectories(sftpConnection, '/Upload/'));// Files List
ClrObject enumerator = list.getEnumerator();
while (enumerator.movenext())
{
totalFiles ++;
sftpFile = enumerator.get_Current();
if(sftpFile != ".." && sftpFile !=null && sftpFile != ".")
{
System.IO.Stream Stream = sftp.DownloadFile(sftpConnection, '/Upload' + '/'+ sftpFile);
this.ReadCSVFile(Stream,sftpFile);
sftp.MoveFile(sftpConnection,
'Import Path'+ '/'+sftpFile,
'destination path'+ '/'+ sftpFile,
false);
}
}
}
catch
{
throw error(infolog.text());
}
finally
{
if(sftpConnection.IsConnected)
sftpConnection.Disconnect();
}
}
}
public boolean ReadCSVFile(System.IO.Stream stream, str fileName)
{
AsciiStreamIo file;
container record;
file = AsciiStreamIo::constructForRead(stream);
if (file)
{
if (file.status())
{
throw error("@SYS52680");
}
file.inFieldDelimiter(',');
file.inRecordDelimiter('\r\n');
while (!file.status())
{
record = file.read();
recordCount++;
if (conLen(record) && recordCount !=1)
{
conPeek(record,2));
}
}
}
return true;
}
Tested in Console Application:
To test in the console application we need to add the class library project as a reference.
We can debug using a console application.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Renci.SshNet;
namespace TestSFTPConnection
{
class Program
{
static void Main(string[] args)
{
SFTPTest.SFTPConnect sftp = new SFTPTest.SFTPConnect();
using (var sftpConnection = sftp.OpenSFTPConnection("Host", 22, "userName", "UserPassword"))
{
//try
{
sftpConnection.ChangeDirectory("/uploads");// folder name
List<string> list = sftp.GetDirectories(sftpConnection, "/uploads/");
List<string>.Enumerator enumerator = list.GetEnumerator();
while (enumerator.MoveNext())
{
string sftpFile = enumerator.Current;
if (sftpFile != ".." && sftpFile != null && sftpFile != ".")
{
System.IO.Stream Stream = sftp.DownloadFile(sftpConnection, "/uploads" + '/' + sftpFile);
}
}
}
}
}
}
}
Reference Link:
https://dynamicsax4u.wordpress.com/2020/08/18/read-files-from-sftp-server-and-write-data-in-ax365-part-2/
Keep Daxing!!