Search code examples
c#csvsftpmemorystreamssh.net

Is it possible to upload a CSV file to an SFTP server directly from a MemoryStream?


Whenever I try to upload a file to the SFTP server with the .csv file extension the only thing within that file is System.IO.MemoryStream. If it's a .txt extension it will have all the values in the file. I can manually convert the .txt to .csv and it will be fine. Is it possible to upload it directly to the SFTP server as a CSV file?

The SFTP Service is using the SSH.NET library by Renci.

Using statement:

using (var stream = csvFileWriter.Write(data, new CsvMapper()))
{
    byte[] file = Encoding.UTF8.GetBytes(stream.ToString());
    sftpService.Put(SftpCredential.Credentials.Id, file, $"/file.csv");
}

SFTP service:

public void Put(int credentialId, byte[] source, string destination)
{
    using (SftpClient client = new SftpClient(GetConnectionInfo(credentialId)))
    {
        ConnectClient(client);

        using (MemoryStream memoryStream = new MemoryStream(source))
        {
            client.BufferSize = 4 * 1024; // bypass Payload error large files
            client.UploadFile(memoryStream, destination);
        }
        DisconnectClient(client);
    }

Solution: The csvFilerWriter I was using returned a Stream not a MemoryStream, so by switching the csvFileWriter and CsvPut() over to MemoryStream it worked.

Updated using statement:

using (var stream = csvFileWriter.Write(data, new CsvMapper()))
{
    stream.Position = 0;
    sftpService.CsvPut(SftpCredential.credemtoa;s.Id, stream, $"/file.csv");
}

Updated SFTP service:

public void CsvPut(int credentialId, MemoryStream source, string destination)
{
    using (SftpClient client = new SftpClient(GetConnectionInfo(credentialId)))
    {
        ConnectClient(client);

        client.BufferSize = 4 * 1024; //bypass Payload error large files
        client.UploadFile(source, destination);

        DisconnectClient(client);
    }
}

Solution

  • It looks like the csvFileWriter.Write already returns MemoryStream. And its ToString returns "System.IO.MemoryStream" string. That's the root source of your problem.

    Aditionally, as you already have the MemoryStream, its an overkill to copy it to yet another MemoryStream, upload it directly. You are copying the data over and over again, it's just a waste of memory.

    Like this:

    var stream = csvFileWriter.Write(data, new CsvMapper());
    stream.Position = 0;
    client.UploadFile(stream, destination); 
    

    See also:


    A simple test code to upload in-memory data:

    var stream = new MemoryStream();
    stream.Write(Encoding.UTF8.GetBytes("this is test"));
    stream.Position = 0;
    
    using (var client = new SftpClient("example.com", "username", "password"))
    {
        client.Connect();
        client.UploadFile(stream, "/remote/path/file.txt");
    }