SftpClient.UploadFile 和 SftpClient.WriteAllBytes 有什么区别?

sco*_*zey 6 .net c# ssh sftp ssh.net

当我使用 SSH.NET 通过 SFTP 传输文件时,我观察到一些奇怪的行为。我正在使用 SFTP 将 XML 文件传输到另一个服务(我不控制)进行处理。如果我使用SftpClient.WriteAllBytes该服务,则会抱怨该文件不是有效的 XML。如果我先写入临时文件然后使用则SftpClient.UploadFile传输成功。

发生了什么?

使用.WriteAllBytes

public void Send(string remoteFilePath, byte[] contents)
{
    using(var client = new SftpClient(new ConnectionInfo(/* username password etc.*/)))
    {
        client.Connect();
        client.WriteAllBytes(remoteFilePath, contents);
    }
}
Run Code Online (Sandbox Code Playgroud)

使用.UploadFile

public void Send(string remoteFilePath, byte[] contents)
{
    var tempFileName = Path.GetTempFileName();
    File.WriteAllBytes(tempFileName, contents);
    using(var fs = new FileStream(tempFile, FileMode.Open))
    using(var client = new SftpClient(new ConnectionInfo(/* username password etc.*/)))
    {
        client.Connect();
        client.UploadFile(fs, targetPath);
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑: Will 在评论中询问我如何将 XML 转换为字节数组。我认为这不相关,但话又说回来,我是问这个问题的人......:P

// somewhere else:
// XDocument xdoc = CreateXDoc();

using(var st = new MemoryStream())
{
    using(var xw = XmlWriter.Create(st, new XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true }))
    {
        xdoc.WriteTo(xw);
    }
    return st.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ryl 1

我可以使用 NuGet 的 SSH.NET 2016.0.0 重现您的问题。但 2016.1.0-beta1 则不然。

检查代码,我可以看到SftpFileStream(使用的WriteAllBytes)一直在写入相同的(起始)数据块。

看来您正遭受此错误的困扰:
https://github.com/sshnet/SSH.NET/issues/70

虽然错误描述没有明确表明这是您的问题,但修复它的提交与我发现的问题相匹配:
考虑 SftpFileStream.Write(byte[] buffer, int offset, int count) when not write 中的偏移量到缓冲区。修复问题#70。


回答你的问题:这些方法的行为确实应该类似。

除了SftpClient.UploadFile针对大量数据的上传进行了优化,而 则SftpClient.WriteAllBytes没有。所以底层的实现是非常不同的。

此外,它SftpClient.WriteAllBytes不会截断现有文件。当您上传的数据少于现有文件的数据时,重要的是。