How to asynchronously send files using a stream?

0 votes
asked Dec 5 by kenswift (140 points)

I am trying to upload a list of files asynchronously using a stream, instead of a file path, but it looks like the handle being returned by the upload is being reused.

BTW - I have tried to upload using the file path and this works, but I am needing to impersonate a different user account and when I try to impersonate it fails inside of the:

task = _sftp.PutFileAsync(localPath, remotePath, null);

Here is part of the logs when trying to send the stream:

2018-12-05 07:57:26.323 INFO Sftp(8)[18] Command: SSHFXPOPEN (10,
'/20181205075650.zip.z04', 26) 2018-12-05 07:57:26.343 INFO
Sftp(8)[18] Response: SSHFXPHANDLE (10, 0x0) 2018-12-05 07:57:26.346
INFO Sftp(8)[18] Command: SSHFXPCLOSE (11, 0x0) 2018-12-05
07:57:26.360 INFO Sftp(8)[18] Response: SSHFXPSTATUS (11, 0, 'OK')
2018-12-05 07:57:26.361 ERROR Sftp(8)[18] Info:
System.ObjectDisposedException: Cannot access a closed file. at
System.IO.Error.FileNotOpen() at System.IO.FileStream.Read(Byte[]
array, Int32 offset, Int32 count) at Rebex.Net.Sftp.IKI(TOU I,
2018-12-05 07:57:26.414 INFO Sftp(8)[99] Command: SSHFXPOPEN (12,
'/20181205075650.zip.z05', 26) 2018-12-05 07:57:26.427 INFO
Sftp(8)[99] Response: SSHFXPHANDLE (12, 0x0) 2018-12-05 07:57:26.429
INFO Sftp(8)[99] Command: SSHFXPCLOSE (13, 0x0) 2018-12-05
07:57:26.441 INFO Sftp(8)[99] Response: SSHFXPSTATUS (13, 0, 'OK')
2018-12-05 07:57:26.442 ERROR Sftp(8)[99] Info:
System.ObjectDisposedException: Cannot access a closed file. at
System.IO.
Error.FileNotOpen() at System.IO.FileStream.Read(Byte[]
array, Int32 offset, Int32 count) at Rebex.Net.Sftp.IKI(TOU I,

Here is most of the code:

List<Task> taskList = new List<Task>();
string[] zipFiles = Directory.GetFiles(Path.Combine(_workingFolder + "\\BBDW"), "*.zip*.*");

foreach (string zipFile in zipFiles)
{
     using (this.impersonate)
     {
          using (FileStream stream = File.Open(zipFile, FileMode.Open))
          {
               Task fileTransfer = _ftpClient.PutFileAsync(stream, _ftpFolder + "/" + Path.GetFileName(zipFile), null);
               taskList.Add(fileTransfer);
          }
     }
}
Applies to: Rebex SFTP

1 Answer

0 votes
answered Dec 5 by Lukas Matyska (47,950 points)

This is bug in your code. You started an asynchronous operation which works with stream and you close the stream immediately after the operation has started.

You have to close the stream after the async operation is finished.

This code will almost never work (it works only when async operation is finished before exiting the using block):

using (stream = File.Open())
{
    Task t = DoSomethingAsync(stream);
}

You have to rewrite your code to use try finally construct.

...