使用winscp session从SFTP进行流式传输。getFile失败– ((winscp.pipestream)流).length'投掷了类型的例外。

发布于 2025-02-11 19:10:06 字数 2763 浏览 1 评论 0 原文

我的应用需要使用SFTP从位置将文件直接复制到Azure存储。 我们的应用程序与.NET 4.6一起使用C#,我们的WINSCP版本为5.21.1。

我的旧代码使用 session.getFileTodirectory()方法起作用,但问题在于它需要将文件存储在我们托管内部的temp文件夹上。

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。 使用我的旧代码,该代码正常工作,该代码仍将其保存到Temp文件夹之前,然后发送到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)流)。lengtth'抛出了类型“ system.notsupportedException”的例外。

这是使用 session.getFile 方法创建流的对象描述

将空流程发送到Azure时,这是'异常stacktrace'

My app requires copying file using SFTP from a location directly to Azure storage.
Our app is using C# with .NET 4.6 and our WinSCP version is 5.21.1.

My old code works using Session.GetFileToDirectory() method, but the problem is it need to store the file on temp folder inside our hosting.

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); 
    }
}

As we planned to entirely use Azure storage, I change my code like this

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);   
    }
}

Here my library that uploads the file using Stream to Azure.
This code is working fine using my old code that still save to temp folder before send to Azure.

public static string UploadToAzure(Stream attachment, string Filename, string Foldername)
{
    System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;

    var connectionString = 
quot;{ConfigurationManager.AppSettings["AzureFileShareConnectionString"]}";
    string shareName = 
quot;{ConfigurationManager.AppSettings["AzureFileShareFolderName"]}";
    string dirName = 
quot;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 
quot;Uploaded {Filename} failed : {e.ToString()}";
    }

    return 
quot;{Filename} Uploaded";
}

But currently my new code not working with error message

'((WinSCP.PipeStream)stream).Length' threw an exception of type 'System.NotSupportedException'.

This is the object description on creating stream using Session.GetFile method
enter image description here

This is 'exception stacktrace' on sending the empty-stream to Azure
enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

木格 2025-02-18 19:10:06

stream winscp sessig 不能实现 stream.length 属性,因为WinSCP无法保证文件的大小已固定。下载文件时,远程文件可能正在更改。更不用说ASCII传输模式了,当文件转换时文件转换时,对最终尺寸的影响不可预测。

您在两个位置使用大小( stream.length ):

  • 创建文件时:

      file.create(actionment.length);
     

    sharefileclient.create maxSize 。因此,它看起来并不是一个实际尺寸。您可能只在这里放一个任意的大数。

    或者如果您喜欢(并且知道文件没有更改),请使用 session.getFileInfo

      file.create(session.getFileInfo(filepath).length);
     
  • 上传内容时:

      file.uploadrange(new httprange(0,attactment.length),附件);
     

    以上可以用简单 sharefileclient.upload

      file.upload(附件);
     

The Stream returned by WinSCP Session.GetFile does not implement the Stream.Length property, because WinSCP cannot guarantee that the size of the file is fixed. The remote file might be changing while you are downloading the file. Not to mention ASCII transfer mode, when the file is converted while being transferred, with unpredictable impact on the final size.

You use the size (Stream.Length) in two places:

  • When creating the file:

    file.Create(attachment.Length);
    

    The parameter of ShareFileClient.Create is maxSize. So it does not look like it's a real size. You can possibly just put an arbitrary large number here.

    Or if you prefer (and know that the file is not changing), read the current size of the remote file using Session.GetFileInfo and RemoteFileInfo.Length:

    file.Create(session.GetFileInfo(FilePath).Length);
    
  • When uploading the contents:

    file.UploadRange(new HttpRange(0, attachment.Length), attachment);
    

    The above can be replaced with simple ShareFileClient.Upload:

    file.Upload(attachment);
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文