You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

libcurl SFTP文件上传断点续传异常:远程文件被截断为0

SFTP断点续传PoC远程文件被截断为0的问题排查与修复

先给你理清楚问题出在哪,以及怎么解决:

我正在开发支持断点续传的SFTP文件上传PoC,基于libcurl官方的FTP断点续传示例修改,做了两个关键改动:

  • 将协议改为sftp协议字符串
  • 在重试循环中强制让c=1,直接进入续传分支

但验证时遇到异常:连接完成后,首次执行curl_perform(...)后,远程文件大小被截断为0。

问题根源分析

libcurl对FTP和SFTP的断点续传逻辑差异很大,你直接照搬FTP示例的强制续传逻辑到SFTP上就踩坑了:

  1. FTP的续传是基于你指定的偏移量直接请求服务器从该位置写入,但SFTP的续传依赖先确认远程文件的当前状态——如果远程文件不存在,你硬指定一个续传偏移量(哪怕是0),libcurl的SFTP驱动会直接创建一个新文件并把偏移量设为你给的值,这就会导致文件被截断成0字节(因为你跳过了“检查远程文件是否存在”的步骤,直接触发了续传分支的逻辑)。
  2. 原FTP示例里的c=1是用来处理中断后的重试续传,它原本会先检查远程文件的大小再设置偏移量,但你强制c=1跳过了这个前置检查,相当于告诉libcurl“不管远程有没有文件,直接从某个位置开始写”,首次上传时远程没有文件,这个操作自然会生成一个0字节的空文件。

修复方案

1. 去掉强制c=1,先检查远程文件状态

在进入续传分支前,必须先确认远程文件是否存在以及它的当前大小,再决定是从头上传还是续传:

// 先切换到HEAD模式,获取远程文件大小
curl_off_t remote_file_size = 0;
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
CURLcode res = curl_easy_perform(curl);

if (res == CURLE_OK) {
    // 获取远程文件的大小
    curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_LARGE, &remote_file_size);
}

// 切回上传模式
curl_easy_setopt(curl, CURLOPT_NOBODY, 0L);

// 根据远程文件状态设置上传模式
if (remote_file_size > 0) {
    // 远程文件存在,开启续传,从文件末尾开始写
    curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, remote_file_size);
} else {
    // 远程文件不存在,从头上传
    curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, 0L);
}

// 执行上传
res = curl_easy_perform(curl);

2. 开启调试日志定位细节

如果还是有问题,打开libcurl的 verbose 日志,查看SFTP的交互过程,确认续传偏移量是否正确,服务器的响应是什么:

curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

3. 确保libcurl版本兼容

一些老版本的libcurl对SFTP续传的支持有缺陷,建议升级到最新的稳定版(比如7.80.0+),避免版本带来的隐性bug。

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

火山引擎 最新活动