c# - SftpClient.UploadFile 和 SftpClient.WriteAllBytes 有什么区别?

标签 c# .net 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);
    }
}

使用 .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);
    }
}

编辑: 将在评论中询问我如何将 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();
}

最佳答案

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

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

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

虽然错误描述没有明确说明这是你的问题,但修复它的提交与我发现的问题相匹配:
Take into account the offset in SftpFileStream.Write(byte[] buffer, int offset, int count) when not writing to the buffer. Fixes issue #70.


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

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

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

关于c# - SftpClient.UploadFile 和 SftpClient.WriteAllBytes 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44185392/

相关文章:

c# - 在 C# 中检查一个整数值是否为 Null

c# - 使用 JSON.NET 将 C# 对象转换为 JSON 时出现额外的 '\'

c# - 从服务中获取登录用户名

bash - 使用 ssh 和 EOF 在 bash 脚本中将变量传递给远程主机

linux - 如何完全删除 Gitosis 然后运行 ​​Gitolite?

c# - RichTextBox 从删除的 'keywords' 中移除颜色

.net - 对象上下文.翻译: avoiding column-mapping mistakes

.net - 没有 MediaTypeFormatter 可用于从媒体类型为 'text/html' 的内容中读取类型的对象

c# - Winforms .Net 简单数据绑定(bind)不起作用

linux - 循环直到连接到 SSH