You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

API无法返回SSH下载的音频文件问题求助

问题分析与解决方案

核心问题原因

  1. 静态SftpClient引发并发冲突
    代码中使用static修饰的s_sftpClient是全局共享变量,多个请求同时调用时会互相干扰:比如一个请求执行Disconnect()会直接中断其他请求的下载操作,导致返回的MemoryStream内容不完整或为空。

  2. APM异步模式的错误使用
    采用BeginDownloadFile+轮询等待的方式不可靠,轮询逻辑可能存在漏洞,导致下载未完全完成就调用EndDownloadFile,最终流数据不完整。

  3. 测试代码中流位置未重置
    测试代码执行callReport.CopyTo(file)后,流的Position已移动到末尾,直接return File时ASP.NET无法读取任何内容,这也验证了流位置对返回结果的影响(原代码中虽设置了Position=0,但其他问题导致流本身无效)。

修复后的代码

1. 修复SSH服务下载方法

public class SshServices
{
    public async Task<MemoryStream> DownloadCallVoiceFile(string uniqueId, CancellationToken cancellationToken)
    {
        // 每个请求创建独立的SftpClient实例,用using自动释放资源
        using var sftpClient = new SftpClient("host", "user", "password");
        await sftpClient.ConnectAsync(cancellationToken);

        if (!sftpClient.IsConnected)
        {
            throw new InvalidOperationException("无法连接到SFTP服务器");
        }

        var serverAddress = @"\file\monitor\saved\Voice.Wav";
        var stream = new MemoryStream();
        
        // 使用原生异步方法替代APM模式,确保下载完全完成
        await sftpClient.DownloadFileAsync(serverAddress, stream, cancellationToken);
        
        sftpClient.Disconnect();
        
        // 重置流位置到起始处,确保ASP.NET能完整读取
        stream.Position = 0;
        
        return stream;
    }
}

2. 修复Controller方法

public virtual async Task<ActionResult> DownloadCallVoiceFile(string uniqueId, CancellationToken cancellationToken)
{
    var callReport = await _callCenterService.DownloadCallVoiceFile(uniqueId, cancellationToken); 
    return File(callReport, "audio/wav", "1.wav"); 
}

3. 修正测试代码(可选)

如果需要保留本地保存测试,需在复制后重置流位置:

public virtual async Task<ActionResult> DownloadCallVoiceFile(string uniqueId, CancellationToken cancellationToken)
{
    var callReport = await _callCenterService.DownloadCallVoiceFile(uniqueId, cancellationToken);
  
    using (FileStream file = new FileStream(@"C:\Users\Ya\Desktop\TestFile.wav", FileMode.Create, FileAccess.Write))
        callReport.CopyTo(file); 

    // 重置流位置到起始处
    callReport.Position = 0;
    return File(callReport, "audio/wav", "1.wav");
}

修复说明

  • 移除static修饰的SftpClient,每个请求使用独立实例,彻底避免并发请求间的资源冲突。
  • 改用DownloadFileAsync原生异步方法,依托async/await确保下载操作完全完成后再执行后续逻辑,消除轮询带来的不确定性。
  • 使用using语句自动释放SftpClient资源,避免连接泄漏。

内容的提问来源于stack exchange,提问作者Yasim Yasin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 15:31:06