0

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);
    }
}
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Aaron FC
  • 27
  • 1
  • 6

2 Answers2

2

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");
}
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
-1

You can avoid the unnecessary using of memory stream like this:

        using (var sftp = new SftpClient(GetConnectionInfo(SftpCredential.GetById(credentialId).Id))))
        {
           sftp.Connect();
           using (var uplfileStream = System.IO.File.OpenRead(fileName))
           {
              sftp.UploadFile(uplfileStream, fileName, true);
           }
           sftp.Disconnect();
        }
Azzy Elvul
  • 1,403
  • 1
  • 12
  • 22
  • It does not look like that the OP is uploading a physical file. – Martin Prikryl Apr 02 '20 at 19:42
  • What do you mean. This piece of code should be wrapped in method and should have several checks before be able to use it. I only demonstrate the idea that the file can be opened as stream and that stream can be passed as parameter to UploadFile to be uploaded. – Azzy Elvul Apr 02 '20 at 20:14
  • But there's no file. OP uploads data generated directly in memory. – Martin Prikryl Apr 03 '20 at 06:04