如何追踪scp/sftp文件传输进度 确认上传完成后执行后续流程
核心问题原因
os.FileInfo是文件元数据的静态快照,你传入函数的fileToUpload是你首次扫描目录时读取的一次性数据,不会自动同步文件系统的实时状态,所以循环中读取的Size()永远是初始时刻的文件大小,不会随文件传输更新。
修复方法
你需要在每次循环判断前,重新调用os.Stat查询目标文件的最新元数据,不要复用初始扫描拿到的os.FileInfo对象,修改后的逻辑参考:
// 入参改为文件路径,不要传入初始扫描得到的静态FileInfo func getFileData(filePath string) { var newSize int64 var currentSize int64 for { // 每次循环都重新拉取最新的文件元数据 fileInfo, err := os.Stat(filePath) if err != nil { // 可根据需要添加错误处理逻辑,比如文件被删除时直接退出 time.Sleep(3 * time.Second) continue } currentSize = fileInfo.Size() fmt.Printf("Current size= %v\n", currentSize) if currentSize != 0 { if currentSize > newSize { newSize = currentSize fmt.Printf("Current size= %v\n", currentSize) fmt.Printf("New size= %v\n", newSize) } else if newSize == currentSize { fmt.Printf("File %s, is done.\n", filePath) break } } time.Sleep(3 * time.Second) } }
可靠性优化建议
- 可以额外增加修改时间检测逻辑,确认文件连续多个检测周期大小、修改时间都没有变化,再判定传输完成,避免传输临时中断导致的误判
- 大多数scp/sftp服务默认会先创建带临时后缀的文件,传输完成后再重命名为正式文件名,你可以调整目录扫描逻辑,忽略
.tmp/.part这类临时后缀的文件,直接处理重命名完成的正式文件,可靠性远高于轮询大小。
内容的提问来源于stack exchange,提问作者user982599
相关产品推荐
相关产品推荐

