Post a reply

Before posting, please read how to report bug or request support effectively.

Bug reports without an attached log file are usually useless.

Options
Add an Attachment

If you do not want to add an Attachment to your Post, please leave the Fields blank.

(maximum 10 MB; please compress large files; only common media, archive, text and programming file formats are allowed)

Options

Topic review

obrynda

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