PutFile using stream does not upload whole file with S3 object stream
Hey, I am trying to use WinSCP Nuget package version 6.5.3 to upload file to FTP server. I have a file stored in AWS S3 and I wanted to use stream variant of PutFile for upload. Problem is that only 17kB out of 10MB are uploaded. It works fine when I copy S3 stream to memory stream first, or if I use temporary file variant PutFiles. Is there a something I am doing wrong? I would expect S3 stream to be like any other stream - it has no problem writing it to file etc.
Thank you for checking.
Here's minimal example and I am also attaching logs for all variants I tested.
Thank you for checking.
Here's minimal example and I am also attaching logs for all variants I tested.
using Amazon.S3;
using Amazon.S3.Model;
using WinSCP;
using Protocol = WinSCP.Protocol;
namespace ConsoleApp1;
class Program
{
private const string ServerUrl = "updateMe";
private const string Username = "updateMe";
private const string Password = "updateMe";
private const string Destination = "updateMe";
private const string S3Bucket = "updateMe";
private const string S3File = "updateMe";
private static readonly AmazonS3Client AmazonS3Client = new ();
static void Main()
{
// doesn't upload whole file - only 17kb
UploadUsingS3Stream().Wait();
// uploads whole file
UploadUsingMemoryStream().Wait();
// uploads whole file
UploadUsingFile().Wait();
}
static async Task UploadUsingS3Stream()
{
using var session = new Session();
session.SessionLogPath = "UploadUsingS3Stream.log";
session.Open(new SessionOptions
{
Protocol = Protocol.Ftp,
HostName = ServerUrl,
PortNumber = 21,
FtpMode = FtpMode.Passive,
UserName = Username,
Password = Password
});
var s3Response = await AmazonS3Client.GetObjectAsync(new GetObjectRequest
{
Key = S3File,
BucketName = S3Bucket
});
session.PutFile(
s3Response.ResponseStream, // using S3 stream directly
Destination + $"/{Guid.NewGuid()}.txt",
new TransferOptions
{
TransferMode = TransferMode.Binary,
PreserveTimestamp = false,
OverwriteMode = OverwriteMode.Overwrite
});
}
static async Task UploadUsingMemoryStream()
{
using var session = new Session();
session.SessionLogPath = "UploadUsingMemoryStream.log";
session.Open(new SessionOptions
{
Protocol = Protocol.Ftp,
HostName = ServerUrl,
PortNumber = 21,
FtpMode = FtpMode.Passive,
UserName = Username,
Password = Password
});
var s3Response = await AmazonS3Client.GetObjectAsync(new GetObjectRequest
{
Key = S3File,
BucketName = S3Bucket
});
// copy to memory stream
var memoryStream = new MemoryStream();
await s3Response.ResponseStream.CopyToAsync(memoryStream);
memoryStream.Position = 0;
session.PutFile(
memoryStream, // using stream copied to memory stream
Destination + $"/{Guid.NewGuid()}.txt",
new TransferOptions
{
TransferMode = TransferMode.Binary,
PreserveTimestamp = false,
OverwriteMode = OverwriteMode.Overwrite
});
}
static async Task UploadUsingFile()
{
using var session = new Session();
session.SessionLogPath = "UploadUsingFile.log";
session.Open(new SessionOptions
{
Protocol = Protocol.Ftp,
HostName = ServerUrl,
PortNumber = 21,
FtpMode = FtpMode.Passive,
UserName = Username,
Password = Password
});
var s3Response = await AmazonS3Client.GetObjectAsync(new GetObjectRequest
{
Key = S3File,
BucketName = S3Bucket
});
// copying to temporary file first
var tempPath = Path.Combine(Path.GetTempPath(), Path.GetTempFileName());
await using var fileStream = new FileStream(tempPath, FileMode.Create, FileAccess.Write);
await s3Response.ResponseStream.CopyToAsync(fileStream);
var result = session.PutFiles(
tempPath, // using file path
Destination + $"/{Guid.NewGuid()}.txt",
false,
new TransferOptions
{
TransferMode = TransferMode.Binary,
PreserveTimestamp = false,
OverwriteMode = OverwriteMode.Overwrite
});
result.Check();
}
}