Although this operation (unzip file after uploading) is not supported by the SFTP protocol (and Rebex SFTP), it is often possible to achieve it by utilizing the fact that SFTP runs over SSH. This makes it possible to use SSH's "remote execute" feature to run arbitrary commands at the server (if it was configured to allow that, of course).
To give it a try, use the following class:
public class SftpCommandRunner
{
private readonly Sftp _sftp;
private readonly StringBuilder _stderr;
private long _exitCode;
public long ExitCode
{
get { return _exitCode; }
}
public string Errors
{
get { return _stderr.ToString(); }
}
public SftpCommandRunner(Sftp sftp)
{
_sftp = sftp;
_stderr = new StringBuilder();
}
public string RunCommand(string command)
{
_stderr.Length = 0;
SshChannel channel = null;
try
{
// start an exec session
channel = _sftp.Session.OpenSession();
channel.RequestExec(command);
// get extended data (used for stderr)
channel.ExtendedDataReceived += new EventHandler<SshExtendedDataReceivedEventArgs>(channel_ExtendedDataReceived);
// receive all response
StringBuilder response = new StringBuilder();
byte[] buffer = new byte[4096];
while (channel.State == SshChannelState.Connected)
{
if (!channel.Poll(_sftp.Timeout * 1000, SocketSelectMode.SelectRead))
break;
int n = channel.Receive(buffer, 0, buffer.Length);
response.Append(_sftp.Encoding.GetString(buffer, 0, n));
}
SshChannelExitStatus exitStatus = channel.ExitStatus;
if (exitStatus != null)
_exitCode = exitStatus.ExitCode;
return response.ToString().TrimEnd();
}
finally
{
if (channel != null)
channel.Close();
}
}
private void channel_ExtendedDataReceived(object sender, SshExtendedDataReceivedEventArgs e)
{
// get extended data
byte[] data = e.GetData();
// convert it to text
string response = _sftp.Encoding.GetString(data, 0, data.Length);
// add it to stderr StringBuilder
_stderr.Append(response);
}
}
To unzip a file located at the server, establish an SFTP connection, upload the file and call SftpCommandRunner.RunCommand, supplying a command to it.
In the sample below, I used the unzip
remote utility to extract the specified file. Of course you can use your favourite unzip utility.
Sftp client = new Sftp();
client.Connect(...);
client.Login(...);
client.ChangeDirectory("upload");
client.PutFile("C:/test.zip", "test.zip");
SftpCommandRunner runner = new SftpCommandRunner(client);
// note the RunCommand has working directory in initial directory
// previous call of client.ChangeDirectory("upload") has no effect to SftpCommandRunner
string result = runner.RunCommand("unzip -o upload/test.zip -d upload");
if (runner.ExitCode == 0)
{
// process command output ...
Console.WriteLine(result);
}
else
{
// process command error output ...
Console.WriteLine("Unzip failed ({0}):", runner.ExitCode);
Console.WriteLine(runner.Errors);
}
If you prefer VB.NET, please let me know.
Does this work for you?