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(); } }