Add UploadFileAsync override with canOverride (#1750)

fixes #1734
This commit is contained in:
mus65
2025-12-23 12:04:27 +01:00
committed by GitHub
parent 4648e0a614
commit adbb68e6e8
3 changed files with 46 additions and 1 deletions
+16
View File
@@ -1133,6 +1133,22 @@ namespace Renci.SshNet
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
Task UploadFileAsync(Stream input, string path, CancellationToken cancellationToken = default);
/// <summary>
/// Asynchronously uploads a <see cref="Stream"/> to a remote file path.
/// </summary>
/// <param name="input">The <see cref="Stream"/> to write to the remote path.</param>
/// <param name="path">The remote file path to write to.</param>
/// <param name="canOverride">Whether the remote file can be overwritten if it already exists.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous upload operation.</returns>
/// <exception cref="ArgumentNullException"><paramref name="input"/> or <paramref name="path"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="path" /> is empty or contains only whitespace characters.</exception>
/// <exception cref="SshConnectionException">Client is not connected.</exception>
/// <exception cref="SftpPermissionDeniedException">Permission to upload the file was denied by the remote host. <para>-or-</para> An SSH command was denied by the server.</exception>
/// <exception cref="SshException">An SSH error where <see cref="Exception.Message" /> is the message from the remote host.</exception>
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
Task UploadFileAsync(Stream input, string path, bool canOverride, CancellationToken cancellationToken = default);
/// <summary>
/// Writes the specified byte array to the specified file, and closes the file.
/// </summary>
+18 -1
View File
@@ -1077,15 +1077,32 @@ namespace Renci.SshNet
/// <inheritdoc />
public Task UploadFileAsync(Stream input, string path, CancellationToken cancellationToken = default)
{
return UploadFileAsync(input, path, canOverride: true, cancellationToken);
}
/// <inheritdoc />
public Task UploadFileAsync(Stream input, string path, bool canOverride, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(input);
ArgumentException.ThrowIfNullOrWhiteSpace(path);
CheckDisposed();
var flags = Flags.Write | Flags.Truncate;
if (canOverride)
{
flags |= Flags.CreateNewOrOpen;
}
else
{
flags |= Flags.CreateNew;
}
return InternalUploadFile(
input,
path,
Flags.Write | Flags.Truncate | Flags.CreateNewOrOpen,
flags,
asyncResult: null,
uploadCallback: null,
isAsync: true,
@@ -74,6 +74,18 @@ namespace Renci.SshNet.IntegrationTests.OldIntegrationTests
await sftp.UploadFileAsync(file, remoteFileName).ConfigureAwait(false);
}
// uploading again should not throw because of the default canOverride = true
using (var file = File.OpenRead(uploadedFileName))
{
await sftp.UploadFileAsync(file, remoteFileName).ConfigureAwait(false);
}
// uploading with canOverride = false should throw because the file already exists
using (var file = File.OpenRead(uploadedFileName))
{
await Assert.ThrowsAsync<SftpException>(async () => await sftp.UploadFileAsync(file, remoteFileName, canOverride: false).ConfigureAwait(false));
}
var downloadedFileName = Path.GetTempFileName();
using (var file = File.OpenWrite(downloadedFileName))