我的应用程序需要使用 SFTP 将文件从某个位置直接复制到 Azure 存储。 我们的应用程序使用 C# 和 .NET 4.6,我们的 WinSCP 版本是 5.21.1。
我的旧代码使用 Session.GetFileToDirectory()
方法工作,但问题是它需要将文件存储在我们托管内的临时文件夹中。
using (Session session = new Session())
{
session.Open(sessionOptions);
TransferOptions transferOptions = new TransferOptions();
transferOptions.TransferMode = TransferMode.Binary;
var transfer = session.GetFileToDirectory(FilePath, fullPath);
using (Stream stream = File.OpenRead(transfer.Destination))
{
UploadToAzure(stream, Filename, Foldername);
}
}
由于我们计划完全使用 Azure 存储,因此我像这样更改了代码
using (Session session = new Session())
{
session.Open(sessionOptions);
TransferOptions transferOptions = new TransferOptions();
transferOptions.TransferMode = TransferMode.Binary;
using (Stream stream = session.GetFile(FilePath, transferOptions))
{
UploadToAzure(stream, Filename, Foldername);
}
}
这是我的库,它使用 Stream
将文件上传到 Azure。
此代码使用我的旧代码运行良好,在发送到 Azure 之前仍然保存到临时文件夹。
public static string UploadToAzure(Stream attachment, string Filename, string Foldername)
{
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
var connectionString = $"{ConfigurationManager.AppSettings["AzureFileShareConnectionString"]}";
string shareName = $"{ConfigurationManager.AppSettings["AzureFileShareFolderName"]}";
string dirName = $"files\\{Foldername}";
string fileName = Filename;
try
{
ShareClient share = new ShareClient(connectionString, shareName);
share.CreateIfNotExists();
ShareDirectoryClient directory = share.GetDirectoryClient(dirName);
directory.CreateIfNotExists();
// Get a reference to a file and upload it
ShareFileClient file = directory.GetFileClient(fileName);
file.Create(attachment.Length);
file.UploadRange(
new HttpRange(0, attachment.Length), attachment);
}
catch (Exception e)
{
return $"Uploaded {Filename} failed : {e.ToString()}";
}
return $"{Filename} Uploaded";
}
但目前我的新代码无法处理错误消息
'((WinSCP.PipeStream)stream).Length' threw an exception of type 'System.NotSupportedException'.
最佳答案
The Stream
returned by WinSCP Session.GetFile
不实现Stream.Length
属性,因为WinSCP不能保证文件的大小是固定的。下载文件时,远程文件可能正在更改。更不用说ASCII传输模式,当文件在传输的同时进行转换,对最终的大小产生不可预测的影响。
您在两个地方使用大小 (Stream.Length
):
创建文件时:
file.Create(attachment.Length);
ShareFileClient.Create
的参数是maxSize
。所以它看起来不像是真实尺寸。您可以在此处输入任意大的数字。或者,如果您愿意(并且知道文件没有更改),可以使用
Session.GetFileInfo
读取远程文件的当前大小。和RemoteFileInfo.Length
:file.Create(session.GetFileInfo(FilePath).Length);
上传内容时:
file.UploadRange(new HttpRange(0, attachment.Length), attachment);
上面可以用简单的
ShareFileClient.Upload
来代替:file.Upload(attachment);
关于c# - 使用 WinSCP Session.GetFile 从 SFTP 进行流式传输失败 – ((WinSCP.PipeStream)stream).Length' 引发类型 'System.NotSupportedException' 的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72809471/