Robbiblubber.Util.FileStorageAdapters.Ftp
1.0.2
dotnet add package Robbiblubber.Util.FileStorageAdapters.Ftp --version 1.0.2
NuGet\Install-Package Robbiblubber.Util.FileStorageAdapters.Ftp -Version 1.0.2
<PackageReference Include="Robbiblubber.Util.FileStorageAdapters.Ftp" Version="1.0.2" />
<PackageVersion Include="Robbiblubber.Util.FileStorageAdapters.Ftp" Version="1.0.2" />
<PackageReference Include="Robbiblubber.Util.FileStorageAdapters.Ftp" />
paket add Robbiblubber.Util.FileStorageAdapters.Ftp --version 1.0.2
#r "nuget: Robbiblubber.Util.FileStorageAdapters.Ftp, 1.0.2"
#:package Robbiblubber.Util.FileStorageAdapters.Ftp@1.0.2
#addin nuget:?package=Robbiblubber.Util.FileStorageAdapters.Ftp&version=1.0.2
#tool nuget:?package=Robbiblubber.Util.FileStorageAdapters.Ftp&version=1.0.2
robbiblubber.org FTP File Storage Adapter Library
The robbiblubber.org FTP File Storage Adapter Library provides access to FTP and FTPS servers through the common API defined by the
FileStorageAdapters Library. Files and directories are exposed through IFile,
IDirectory, and IElement.
The repository can be found at https://bitbucket.org/robbiblubber/robbiblubber.util.filestorageadapters.net/. API documentation is available from https://robbiblubber.lima-city.org/. For general information see http://robbiblubber.org/.
The library is provided under the MIT license and may be used under the conditions of that license agreement.
Opening a Directory
Connection behavior can be configured with FtpAdapterOptions:
using Robbiblubber.Util.FileStorageAdapters;
using Robbiblubber.Util.FileStorageAdapters.Ftp;
FtpAdapterOptions options = new()
{
Security = FtpSecurity.ExplicitTls,
DataConnectionMode = FtpDataConnectionMode.Passive,
InternetProtocol = FtpInternetProtocol.Any,
ConnectTimeout = TimeSpan.FromSeconds(30),
DataConnectionConnectTimeout = TimeSpan.FromSeconds(30),
SocketKeepAlive = true
};
using FtpAdapter adapter = new("ftp.example.org", 21, "username", "password", options);
IDirectory directory = adapter.OpenDirectory("/incoming");
The directory must already exist. Keep the adapter alive while using its elements, and dispose it after those operations are complete. Completed read snapshots remain usable after adapter disposal.
Connection Settings
FtpSecurity.None, ExplicitTls, and ImplicitTls select plain FTP, explicit
FTPS, and implicit FTPS. The default is None; select a TLS mode explicitly
when encryption is required. FTPS and SFTP are different protocols; use
SftpAdapter from the SSH adapter library for an SFTP server.
Options also cover active or passive data connections, IP protocol selection, control and data connection timeouts, keep-alive, and command/name encoding.
Normal FTPS server certificate validation is enabled by default. Set AcceptAnyCertificate only
for deliberately insecure connections, for example in a controlled test environment.
Persisted Attachment Configurations
FtpAttachConfig exposes the FTP connection parameters as properties. It can be created from a host or
from an existing FtpAdapter. Serialized configurations are opened provider-neutrally through
AttachConfig.Open:
using System.Text.Json.Nodes;
FtpAttachConfig config = new(adapter)
{
InitialPath = "/incoming"
};
JsonObject data = config.Serialize();
AttachConfig restored = AttachConfig.Open(data);
using FtpAdapter restoredAdapter = (FtpAdapter) restored.CreateAdapter();
IDirectory restoredDirectory = restoredAdapter.OpenDirectory(restored.InitialPath);
The JSON representation contains a format version and the ftp adapter discriminator. If a password
is configured, it is part of the serialized configuration. The shell can protect the complete serialized
configuration with its attach --save --password option.
Supported Operations
The adapter supports listing, path lookup, name filtering, stream-based reads, file and directory creation and deletion, recursive copy and move, and local upload and download through the common FileStorageAdapters API.
Files can be transferred to and from other adapters through streams. Directory
transfers are recursive. CopyToAsync(destination) places the source inside
the destination directory under its existing name; the overload with a name
argument selects a different destination name.
Existing content is not overwritten unless overwrite is true. Copying a
directory into an existing directory of the same name with overwrite enabled
merges the contents and retains unrelated destination files. Cross-adapter
moves copy the content before deleting the source and are not atomic.
Paths and Metadata
/ denotes the root exposed by the FTP server. The initial directory is a
starting point, not an additional navigation boundary. Relative paths are
resolved from the directory context; . and .. are supported, and both /
and \ are accepted as logical separators.
Metadata depends on the server's listing and command support. Directory sizes
are calculated recursively and can require many server requests. Content types
and ETags are returned as null.
Example
With directory opened as shown above:
IFile source = await directory.GetFileAsync("report.txt");
await using Stream content = await source.ReadAsync();
IDirectory output = await directory.CreateDirectoryAsync("processed");
IFile copy = await output.CreateFileAsync("report.txt", content, overwrite: true);
Console.WriteLine(copy.Path);
Streams returned by ReadAsync are owned by the caller and must be disposed.
Streams supplied to CreateFileAsync remain owned by the caller and are not
disposed by the adapter.
Concurrent access and buffered reads
Client operations on one adapter are serialized. ReadAsync downloads the entire
file into temporary local storage before returning a read-only, seekable stream.
The returned stream does not hold the adapter connection or its operation gate.
Dispose each returned stream to remove its temporary storage. Each stream supports
one consumer; do not concurrently read, seek or dispose that same stream.
DisposeAsync rejects new client accesses and waits for the active client access
before closing the connection. Dispose waits synchronously for the same result.
A copy or recursive transfer consists of several accesses and can fail between
steps if its adapter is closed early. Neither copies nor moves are transactions.
Use an exclusively owned client; externally supplied streams must not re-enter
the destination adapter from their read or dispose callbacks during an upload.
See THREAD-SAFETY-PLAN.md in the source archive for the implementation stage,
remaining conflict-handling work and validation status.
Conflict guarantees
Standard FTP cannot atomically create a caller-named file only if absent. The existence check is serialized within one adapter, but other clients can still race it. Do not rely on overwrite:false as a cross-client create-only guarantee.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- FluentFTP (>= 55.1.0)
- Robbiblubber.Util.FileStorageAdapters (>= 1.0.2)
-
net8.0
- FluentFTP (>= 55.1.0)
- Robbiblubber.Util.FileStorageAdapters (>= 1.0.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.