Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion FileSystem.Adapters.AmazonS3/src/AmazonS3Adapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ public override void Dispose()
client.Dispose();
}

public override void Connect()
public override async Task ConnectAsync(CancellationToken cancellationToken = default)
{
Logger.LogStartConnectingAdapter(this);
await Task.CompletedTask;
Logger.LogFinishedConnectingAdapter(this);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ public override void Dispose()
{
}

public override void Connect()
public override async Task ConnectAsync(CancellationToken cancellationToken = default)
{
Logger.LogStartConnectingAdapter(this);
await Task.CompletedTask;
Logger.LogFinishedConnectingAdapter(this);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ public override void Dispose()
{
}

public override void Connect()
public override async Task ConnectAsync(CancellationToken cancellationToken = default)
{
Logger.LogStartConnectingAdapter(this);
await Task.CompletedTask;
Logger.LogFinishedConnectingAdapter(this);
}

Expand Down
3 changes: 2 additions & 1 deletion FileSystem.Adapters.Dropbox/src/DropboxAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ public override void Dispose()
client.Dispose();
}

public override void Connect()
public override async Task ConnectAsync(CancellationToken cancellationToken = default)
{
Logger.LogStartConnectingAdapter(this);
await Task.CompletedTask;
Logger.LogFinishedConnectingAdapter(this);
}

Expand Down
31 changes: 31 additions & 0 deletions FileSystem.Adapters.Ftp/FileSystem.Adapters.Ftp.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<RootNamespace>SharpGrip.FileSystem.Adapters.Ftp</RootNamespace>
</PropertyGroup>

<PropertyGroup>
<AssemblyName>SharpGrip.FileSystem.Adapters.Ftp</AssemblyName>
<PackageId>SharpGrip.FileSystem.Adapters.Ftp</PackageId>
<Title>SharpGrip FileSystem FTP adapter</Title>
<Description>The SharpGrip FileSystem FTP adapter.</Description>
<PackageTags>sharpgrip;file-system;ftp</PackageTags>
</PropertyGroup>

<ItemGroup>
<None Include="..\README.md" Pack="true" PackagePath="\" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="FluentFTP" Version="49.0.1" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\FileSystem\FileSystem.csproj" />
</ItemGroup>

</Project>
253 changes: 253 additions & 0 deletions FileSystem.Adapters.Ftp/src/FtpAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using FluentFTP;
using FluentFTP.Exceptions;
using SharpGrip.FileSystem.Constants;
using SharpGrip.FileSystem.Exceptions;
using SharpGrip.FileSystem.Extensions;
using SharpGrip.FileSystem.Models;
using SharpGrip.FileSystem.Utilities;
using DirectoryNotFoundException = SharpGrip.FileSystem.Exceptions.DirectoryNotFoundException;
using FileNotFoundException = SharpGrip.FileSystem.Exceptions.FileNotFoundException;

namespace SharpGrip.FileSystem.Adapters.Ftp
{
public class FtpAdapter : Adapter<FtpAdapterConfiguration, string, string>
{
private readonly IAsyncFtpClient client;

public FtpAdapter(string prefix, string rootPath, IAsyncFtpClient client, Action<FtpAdapterConfiguration>? configuration = null) : base(prefix, rootPath, configuration)
{
this.client = client;
}

public override void Dispose()
{
client.Dispose();
}

public override async Task ConnectAsync(CancellationToken cancellationToken = default)
{
if (client.IsConnected)
{
return;
}

try
{
Logger.LogStartConnectingAdapter(this);
await client.Connect(cancellationToken);
Logger.LogFinishedConnectingAdapter(this);
}
catch (Exception exception)
{
throw Exception(exception);
}
}

public override async Task<IFile> GetFileAsync(string virtualPath, CancellationToken cancellationToken = default)
{
var path = GetPath(virtualPath);

try
{
var file = await client.GetObjectInfo(path, token: cancellationToken);

if (file == null || file.Type != FtpObjectType.File)
{
throw new FileNotFoundException(path, Prefix);
}

return ModelFactory.CreateFile(file, virtualPath);
}
catch (Exception exception)
{
throw Exception(exception);
}
}

public override async Task<IDirectory> GetDirectoryAsync(string virtualPath, CancellationToken cancellationToken = default)
{
var path = GetPath(virtualPath);

try
{
var directory = await client.GetObjectInfo(path, token: cancellationToken);

if (directory == null || directory.Type != FtpObjectType.Directory)
{
throw new DirectoryNotFoundException(path, Prefix);
}

return ModelFactory.CreateDirectory(directory, virtualPath);
}
catch (Exception exception)
{
throw Exception(exception);
}
}

public override async Task<IEnumerable<IFile>> GetFilesAsync(string virtualPath = "", CancellationToken cancellationToken = default)
{
await GetDirectoryAsync(virtualPath, cancellationToken);
var path = GetPath(virtualPath);

try
{
var ftpListItems = await client.GetListing(path, cancellationToken);

return ftpListItems.Where(file => file.Type == FtpObjectType.File).Select(file => ModelFactory.CreateFile(file, GetVirtualPath(file.FullName)));
}
catch (Exception exception)
{
throw Exception(exception);
}
}

public override async Task<IEnumerable<IDirectory>> GetDirectoriesAsync(string virtualPath = "", CancellationToken cancellationToken = default)
{
await GetDirectoryAsync(virtualPath, cancellationToken);
var path = GetPath(virtualPath);

try
{
var ftpListItems = await client.GetListing(path, cancellationToken);

return ftpListItems.Where(file => file.Type == FtpObjectType.Directory).Select(file => ModelFactory.CreateDirectory(file, GetVirtualPath(file.FullName)));
}
catch (Exception exception)
{
throw Exception(exception);
}
}

public override async Task CreateDirectoryAsync(string virtualPath, CancellationToken cancellationToken = default)
{
if (await DirectoryExistsAsync(virtualPath, cancellationToken))
{
throw new DirectoryExistsException(GetPath(virtualPath), Prefix);
}

try
{
await client.CreateDirectory(GetPath(virtualPath), cancellationToken);
}
catch (Exception exception)
{
throw Exception(exception);
}
}

public override async Task DeleteDirectoryAsync(string virtualPath, CancellationToken cancellationToken = default)
{
await GetDirectoryAsync(virtualPath, cancellationToken);

try
{
await client.DeleteDirectory(GetPath(virtualPath), cancellationToken);
}
catch (Exception exception)
{
throw Exception(exception);
}
}

public override async Task DeleteFileAsync(string virtualPath, CancellationToken cancellationToken = default)
{
await GetFileAsync(virtualPath, cancellationToken);

try
{
await client.DeleteFile(GetPath(virtualPath), cancellationToken);
}
catch (Exception exception)
{
throw Exception(exception);
}
}

public override async Task<Stream> ReadFileStreamAsync(string virtualPath, CancellationToken cancellationToken = default)
{
await GetFileAsync(virtualPath, cancellationToken);

try
{
var fileStream = await client.OpenRead(GetPath(virtualPath), token: cancellationToken);

return await StreamUtilities.CopyContentsToMemoryStreamAsync(fileStream, true, cancellationToken);
}
catch (Exception exception)
{
throw Exception(exception);
}
}

public override async Task WriteFileAsync(string virtualPath, Stream contents, bool overwrite = false, CancellationToken cancellationToken = default)
{
if (!overwrite && await FileExistsAsync(virtualPath, cancellationToken))
{
throw new FileExistsException(GetPath(virtualPath), Prefix);
}

try
{
contents.Seek(0, SeekOrigin.Begin);

using var writeStream = await client.OpenWrite(GetPath(virtualPath), token: cancellationToken);

await contents.CopyToAsync(writeStream, FileSystemConstants.Streaming.DefaultMemoryStreamBufferSize, cancellationToken);
await writeStream.FlushAsync(cancellationToken);
}
catch (Exception exception)
{
throw Exception(exception);
}
}

public override async Task AppendFileAsync(string virtualPath, Stream contents, CancellationToken cancellationToken = default)
{
await GetFileAsync(virtualPath, cancellationToken);

try
{
using var fileStream = await client.OpenAppend(GetPath(virtualPath), token: cancellationToken);

await contents.CopyToAsync(fileStream);
}
catch (Exception exception)
{
throw new AdapterRuntimeException(exception);
}
}

protected override Exception Exception(Exception exception)
{
if (exception is FileSystemException)
{
return exception;
}

if (exception is SocketException socketException)
{
return new ConnectionException(socketException);
}

if (exception is FtpAuthenticationException ftpAuthenticationException)
{
return new ConnectionException(ftpAuthenticationException);
}

if (exception is FtpSecurityNotAvailableException ftpSecurityNotAvailableException)
{
return new ConnectionException(ftpSecurityNotAvailableException);
}

return new AdapterRuntimeException(exception);
}
}
}
8 changes: 8 additions & 0 deletions FileSystem.Adapters.Ftp/src/FtpAdapterConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using SharpGrip.FileSystem.Configuration;

namespace SharpGrip.FileSystem.Adapters.Ftp
{
public class FtpAdapterConfiguration : AdapterConfiguration
{
}
}
33 changes: 33 additions & 0 deletions FileSystem.Adapters.Ftp/src/ModelFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using FluentFTP;
using SharpGrip.FileSystem.Models;

namespace SharpGrip.FileSystem.Adapters.Ftp
{
public static class ModelFactory
{
public static IFile CreateFile(FtpListItem file, string virtualPath)
{
return new FileModel
{
Name = file.Name,
Path = file.FullName,
VirtualPath = virtualPath,
Length = file.Size,
LastModifiedDateTime = file.Modified,
CreatedDateTime = file.Created
};
}

public static DirectoryModel CreateDirectory(FtpListItem directory, string virtualPath)
{
return new DirectoryModel
{
Name = directory.Name,
Path = directory.FullName,
VirtualPath = virtualPath,
LastModifiedDateTime = directory.Modified,
CreatedDateTime = directory.Created
};
}
}
}
3 changes: 2 additions & 1 deletion FileSystem.Adapters.GoogleDrive/src/GoogleDriveAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ public override void Dispose()
client.Dispose();
}

public override void Connect()
public override async Task ConnectAsync(CancellationToken cancellationToken = default)
{
Logger.LogStartConnectingAdapter(this);
await Task.CompletedTask;
Logger.LogFinishedConnectingAdapter(this);
}

Expand Down
Loading