使用Golang AWS SDK V2下载S3 Bucket文件夹内文件报错无此文件或目录
问题原因
你的错误出现在os.Create(*item.Key)执行阶段:S3对象的Key包含层级路径前缀(比如data/backup/20240520.tar这种带/的格式),操作系统不会自动创建路径中不存在的父目录,因此直接用Key作为本地路径创建文件时,就会抛出no such file or directory错误。
修复逻辑
需要做三处调整:
- 导入
path/filepath和strings依赖包 - 跳过S3的文件夹占位对象(Key以/结尾、大小为0的虚拟对象),避免无意义的创建操作
- 创建本地文件前,先递归创建Key对应的父目录
核心修改代码
// 新增导入 import ( "path/filepath" "strings" // 保留原有其他导入 ) // main函数中循环下载部分修改为以下逻辑 for _, item := range resp.Contents { diff := today.Sub(*item.LastModified) if diff.Hours() <= 24 { key := *item.Key // 跳过文件夹占位对象 if strings.HasSuffix(key, "/") { continue } fmt.Println("Name: ", key) fmt.Println("Last modified: ", *item.LastModified) fmt.Println("Size: ", item.Size) fmt.Println("Storage class: ", item.StorageClass) fmt.Println("") // 递归创建父目录 dirPath := filepath.Dir(key) if err := os.MkdirAll(dirPath, 0755); err != nil { log.Printf("创建目录失败: %v, 跳过文件%v", err, key) continue } newFile, err := os.Create(key) if err != nil { log.Printf("创建本地文件失败: %v, 跳过文件%v", err, key) continue } numBytes, err := downloader.Download(context.TODO(), newFile, &s3.GetObjectInput{ Bucket: aws.String(BUCKET), Key: aws.String(key), }) // 手动关闭文件,不要在循环内使用defer(defer会等到main函数退出才执行,会占用过多文件句柄) newFile.Close() if err != nil { fmt.Printf("下载备份%v失败: %v\n", key, err) continue } fmt.Printf("下载完成,%v 共%v字节\n", key, numBytes) } }
可选优化
如果你不需要在本地保留S3的目录结构,只想把所有tar文件下载到当前目录,可以直接用文件名作为本地路径,不需要创建父目录:
// 替换os.Create行即可,无需执行MkdirAll newFile, err := os.Create(filepath.Base(key))
内容的提问来源于stack exchange,提问作者AR7
相关产品推荐
相关产品推荐

