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

CopyToAsync下载图片后FluentFTP上传报错,如何用async/await解决

问题修复方案

问题根源

  • 调用异步方法DownloadImage时未添加await关键字,导致下载逻辑未执行完成就提前执行后续文件检查和FTP上传逻辑
  • DownloadImage内部混用阻塞式调用.Result和await,既可能引发线程死锁,也会打乱异步执行时序
  • 未对下载失败的场景做处理,可能出现下载未成功但后续逻辑仍然执行的情况

修复步骤

1. 修正DownloadImage方法的异步实现

调整异步调用逻辑,优化路径拼接,增加下载结果返回:

// 可根据需要修改返回值,示例返回下载成功的完整路径,失败返回null
public static async Task<string> DownloadImage(Entity.LoginResult loginResult, string saveFolder, string image, string saveFile)
{
    string filename = Path.GetFileNameWithoutExtension(saveFile);
    string extension = Path.GetExtension(saveFile);
    saveFile = GetValidUrlString(filename, "-", 255) + extension;
    // 用Path.Combine拼接路径,避免手动拼接斜杠出错
    string fullSavePath = Path.Combine(saveFolder, saveFile);
    
    // 注意:生产环境建议复用HttpClient静态实例,不要每次请求都new,避免端口耗尽问题
    using (var httpClient = new HttpClient())
    {
        using (var request = new HttpRequestMessage(HttpMethod.Get, apiUrl + image + "/download"))
        {
            request.Headers.TryAddWithoutValidation("Authorization", "CBX-SIMPLE-TOKEN Token=" + loginResult.token);
            // 替换阻塞式.Result为await,符合异步开发规范
            var response = await httpClient.SendAsync(request);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                using (var fs = new FileStream(fullSavePath, FileMode.Create))
                {                                
                    await response.Content.CopyToAsync(fs);
                }
                return fullSavePath;
            }
            return null;
        }
    }
}

2. 修正调用逻辑,等待下载完成再执行后续操作

// 调用时必须添加await,等待下载逻辑完全执行完成后再走后续流程
var downloadedFilePath = await DownloadImage(loginResult, saveFolder, image, saveFile);

// 直接判断返回的路径有效性即可
if (!string.IsNullOrEmpty(downloadedFilePath) && File.Exists(downloadedFilePath))
{ 
    // 此时文件已经完成写入、流已经自动释放,不会出现文件占用问题,直接执行FTP上传
    CallFtpUpload(downloadedFilePath);  
}

补充说明

  • await执行完成后,FileStream的using块已经自动释放文件锁,不会出现文件被占用的问题
  • 如果需要兼容非异步上下文的调用场景,可以用DownloadImage(...).GetAwaiter().GetResult()代替.Result避免死锁,优先推荐全链路使用await
  • 可根据业务需要添加下载失败重试逻辑,避免偶发网络问题导致流程中断

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 08:21:02