EldoS | Feel safer!

Software components for data protection, secure storage and transfer

TElSimpleSFTPClient.UploadStream help

Also by EldoS: Rethync
The cross-platform framework that simplifies synchronizing data between mobile and desktop applications and servers and cloud storages
#19218
Posted: 02/27/2012 10:36:42
by Andy Gardner (SUPPORT DISABLED)
Joined: 02/17/2012
Posts: 51

I am attempting to use TElSimpleSFTPClient.UploadStream to upload an XML file created using an XmlWriter. The file is created on the server, but the contents are never written to it.

The UploadStream call never returns, and the OnProgress event on the TElSimpleSFTPClient is never fired.

If I put the following code before the UploadStream call, I am able to read the full XML contents back:
Code
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(stream))
{
    TextReader reader = sr as TextReader;
    string line;
    while ((line = reader.ReadLine()) != null)
    {
       sb.AppendLine(line);
    }
}


Is there anything that might prevent UploadStream from completing the stream read? The only example for UploadStream I could find was in the SftpUpload_ASPNET20 project, but I couldn't seen anything different.

Thank you,

Andy
#19219
Posted: 02/27/2012 10:44:27
by Vsevolod Ievgiienko (EldoS Corp.)

Thank you for contacting us.

Could you please post here a code used to create the XML and upload a file. You can also create a ticket in Helpdesk and upload a full project there: https://www.eldos.com/helpdesk/index.php

Could you also clarify what SBB version do you use.
#19225
Posted: 02/27/2012 16:32:04
by Andy Gardner (SUPPORT DISABLED)
Joined: 02/17/2012
Posts: 51

I am using SBB 9.1.214 with an evaluation license. The project I am working with is too large to upload, and I would rather not create another project if it isn't necessary.

The code to create the XML using XmlWriter is as follows:

Code
XmlWriterSettings settings = new
settings.Indent = true;
using (StreamWriter sw = new StreamWriter(
files.UploadFile(node.CombineDir(d, InputVariablesFile))))
using (XmlWriter xw = XmlWriter.Create(sw, settings))
{
    variables.WriteXml(xw);
}


The files variable is a wrapper class for TElSimpleSFTPClient. The UploadFile method is:
Code
public Stream UploadFile(string dest)
{
   AnonymousPipeServerStream pipeServer =
      new AnonymousPipeServerStream(
         PipeDirection.Out,
         HandleInheritability.Inheritable);
   DisposeBlockingStream uploadStream = new DisposeBlockingStream(pipeServer);
   sftpClient.OnProgress += uploadStream.OnProgress;

   PipeStream pipeClient = new AnonymousPipeClientStream(
      PipeDirection.In,
      pipeServer.GetClientHandleAsString());

   bw.DoWork += fileUploader_DoWork;
   bw.RunWorkerAsync(new object[] { pipeClient, dest });

   return uploadStream;
}


The DisposeBlockingStream class is a wrapper implementation of Stream That prevents disposal until a CanDispose property is set. I put this in to block leaving the using statement for the XML until after the file upload had completed. The CanDispose is set in the OnProgress event handler of the TElSimpleSFTPClient.

The fileUploader_DoWork handler looks like:
Code
private void fileUploader_DoWork(object sender, DoWorkEventArgs e)
{
Debug.Assert(sftpClient.Active,
   "SFTP client connection should be active.");

bw.DoWork -= fileUploader_DoWork;

object[] args = e.Argument as object[];

Debug.Assert(args.Length == 2,
   "fileUploader_DoWork needs two arguments.");

Stream stream = args[0] as Stream;
string dest = args[1] as string;

Debug.Assert(stream != null, "Stream to upload is null");
Debug.Assert(!string.IsNullOrEmpty(dest),
   "Destination is null or empty.");

/*StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(stream))
{
   TextReader reader = sr as TextReader;
   string line;
   while ((line = reader.ReadLine()) != null)
   {
      sb.AppendLine(line);
   }
}*/

sftpClient.UploadStream(
   stream,
   dest,
   TSBFileTransferMode.ftmOverwrite);
}


If I uncomment the StringBuilder code, it will contain the correct XML when the UploadStream method is reached.

Please let me know if I have left out something you need to see.

Thank you,

Andy
#19227
Posted: 02/28/2012 01:34:42
by Vsevolod Ievgiienko (EldoS Corp.)

Again its not clear what is the reason of error from your code. Lets try to do next:

1) check if a file can be uploaded using our SimpleSFTPDemo sample. It uses UploadFile() method that uses UploadStream() internally so if it works then the problem is in your code.
2) check you OnProgress event handler. Its Cancel parameter should not be set to 'true'.
3) try to replace DisposeBlockingStream with standard MemoryStream/FileStream and check if the problem still exists.
#19229
Posted: 02/28/2012 01:49:41
by Eugene Mayevski (EldoS Corp.)

Also please take a look at our support policy. Basic support, provided for trial users, doesn't include working with their code. Nevertheless we agreed to look at your sample and work with it, however, you don't even want to create one, and instead post unrelated pieces of code, which we have to decipher to understand what's going on there.

I don't think that we can provide effective assistance with this approach. If you give us a complete and clear test case which shows the problem, we will be able to run it and say what's up there. The test case doesn't need to generate new XML or run a secondary thread. But it needs to include key blocks, such as DisposeBlockingStream and those pipe streams.

I believe that the problem is in pipes in your case. And to solve it we do need the working code.


Sincerely yours
Eugene Mayevski
#19252
Posted: 02/29/2012 08:23:49
by Andy Gardner (SUPPORT DISABLED)
Joined: 02/17/2012
Posts: 51

I have managed to track down the problem. The pipe stream is throwing an exception because UploadStream is trying to get it's length. Is it possible to upload a stream with an indeterminate size?

Quote
System.NotSupportedException was caught
Message=Stream does not support seeking.
Source=System.Core
StackTrace:
at System.IO.__Error.SeekNotSupported()
at System.IO.Pipes.PipeStream.get_Length()
at SBSimpleSftp.TElSimpleSFTPClient.UploadStream(Stream LocalStream, String RemoteFileName, TSBFileTransferMode Mode, Int64 RestartFrom)
at SBSimpleSftp.TElSimpleSFTPClient.UploadStream(Stream LocalStream, String RemoteFileName, TSBFileTransferMode Mode)
at StreamUploadTest.SSHFiles.fileUploader_DoWork(Object sender, DoWorkEventArgs e) in C:\SourceCode\StreamUploadTest\SSHFiles.cs:line 353
InnerException:
#19253
Posted: 02/29/2012 08:31:25
by Vsevolod Ievgiienko (EldoS Corp.)

Indeed UploadStream() tries to get stream length. You can override this problem using a sequence of TElSimpleSftpClient.OpenFile/Write/CloseHandle methods and reading input data for Write method manually.
#19256
Posted: 02/29/2012 10:28:27
by Eugene Mayevski (EldoS Corp.)

Quote
Andy Gardner wrote:
The pipe stream is throwing an exception because UploadStream is trying to get it's length.


That's exactly what I suspected and wanted to check myself by running the sample.
We will make necessary improvements for SecureBlackbox 10 to handle such streams.


Sincerely yours
Eugene Mayevski
#19268
Posted: 03/01/2012 09:15:26
by Andy Gardner (SUPPORT DISABLED)
Joined: 02/17/2012
Posts: 51

Thank you for the help,

Andy
#19269
Posted: 03/01/2012 11:41:24
by Eugene Mayevski (EldoS Corp.)

FWIW we have already implemented changes to handle such streams. Changes will go to version 10 of SBB though.


Sincerely yours
Eugene Mayevski
Also by EldoS: Rethync
The cross-platform framework that simplifies synchronizing data between mobile and desktop applications and servers and cloud storages

Reply

Statistics

Topic viewed 3931 times

Number of guests: 1, registered members: 0, in total hidden: 0




|

Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!