背景:
腾讯云账号下,有很多对象存储COS桶:
我当初想确认某一个对象存储桶的沉闷水平,简略的来说。我想晓得这个桶外面最初上传的一个文件是什么,以及它的上传工夫戳。
本文将介绍如何应用腾讯云对象存储(COS)的 Go 语言 SDK 查问指定存储桶中的最新文件信息,包含文件门路和上传工夫。本教程假如读者曾经具备根本的 Go 语言编程常识,并且对腾讯云 COS 有肯定的理解。
应用腾讯云go sdk 查问对象存储中最新文件
前置条件
- 您须要领有一个腾讯云账号,并创立了至多一个COS存储桶。
- 理解Go语言和根本的并发编程常识。
确保您已装置Go运行时环境。
装置腾讯云COS Go SDK
在开始之前,先确保您的开发环境已装置了腾讯云COS的Go SDK。如果尚未装置,能够应用以下Go命令装置:
mkdir xxxxgo mod int xxxxgo get github.com/tencentyun/cos-go-sdk-v5
咱们这里的操作是属于List Object 参照:GetBucket
第一版代码:
应用chatgpt生成第一版代码:
main.go
package mainimport ( "context" "fmt" "net/http" "net/url" "sort" "time" "github.com/tencentyun/cos-go-sdk-v5")// 请替换上面的假如值为理论的 SecretId、SecretKey、BucketName 和 Region。const ( SecretId = "xxxxxx" SecretKey = "xxxx" BucketName = "xxxxxx" // 例如 "example-1250000000" BucketRegion = "ap-shanghai" // 例如 "ap-guangzhou")func main() { u, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", BucketName, BucketRegion)) b := &cos.BaseURL{BucketURL: u} client := cos.NewClient(b, &http.Client{ Transport: &cos.AuthorizationTransport{ SecretID: SecretId, SecretKey: SecretKey, }, }) c := context.Background() opt := &cos.BucketGetOptions{ MaxKeys: 1000, // 批改这个值以获取更多或更少的对象 } v, _, err := client.Bucket.Get(c, opt) if err != nil { panic(err) } // 对后果进行排序,找到最初更新的对象 if len(v.Contents) > 0 { sort.Slice(v.Contents, func(i, j int) bool { ti, _ := time.Parse(time.RFC3339, v.Contents[i].LastModified) tj, _ := time.Parse(time.RFC3339, v.Contents[j].LastModified) return ti.After(tj) }) lastUpdatedObj := v.Contents[0] fmt.Printf("最新上传文件门路: %s\n", lastUpdatedObj.Key) fmt.Printf("最新上传工夫: %s\n", lastUpdatedObj.LastModified) } else { fmt.Println("桶中没有文件。") }}
运行main.go
go run main.go
运行后兴许感觉是正确的,毕竟没有报错。然而这里是有问题的,为什么呢?因为我自身不晓得最初一个文件是什么,我手动上传了一个文件,最初一个文件应该是输入:go1.22.0.linux-amd64.tar.gz!
什么起因呢?问题应该是在这里:
c := context.Background() opt := &cos.BucketGetOptions{ MaxKeys: 1000, // 批改这个值以获取更多或更少的对象 }
marker标记参数没有设置
持续批改欠缺main.go代码:
package mainimport ( "context" "fmt" "net/http" "net/url" "sort" "time" "github.com/tencentyun/cos-go-sdk-v5")// 请替换以下的假如值为理论的 SecretId、SecretKey、BucketName 和 Region。const ( SecretId = "xxxxxx" SecretKey = "xxxx" BucketName = "xxxxxx" // 例如 "example-1250000000" BucketRegion = "ap-shanghai" // 例如 "ap-guangzhou")func main() { u, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", BucketName, BucketRegion)) b := &cos.BaseURL{BucketURL: u} client := cos.NewClient(b, &http.Client{ Transport: &cos.AuthorizationTransport{ SecretID: SecretId, SecretKey: SecretKey, }, }) c := context.Background() var lastUpdatedObj *cos.Object isTruncated := true nextMarker := "" for isTruncated { opt := &cos.BucketGetOptions{ Marker: nextMarker, MaxKeys: 1000, // 单次申请返回的最大对象数 } v, _, err := client.Bucket.Get(c, opt) if err != nil { panic(err) } for _, object := range v.Contents { if lastUpdatedObj == nil || object.LastModified > lastUpdatedObj.LastModified { lastUpdatedObj = &object } } // 更新下一个标记和是否截断的标记 isTruncated = v.IsTruncated nextMarker = v.NextMarker } // 查看是否有对象被找到 if lastUpdatedObj != nil { fmt.Printf("最新上传文件门路: %s\n", lastUpdatedObj.Key) fmt.Printf("最新上传工夫: %s\n", lastUpdatedObj.LastModified) } else { fmt.Println("桶中没有文件。") }}
运行批改后的main.go文件:
go run main.go
输入go1.22.0.linux-amd64.tar.gz这个起码是正确的!
拆分代码
想持续拆分一下,将客户端的创立和查找逻辑拆分到两个独立的函数createCOSClient getLastUpdatedFileInfo,而后main函数中调用:
package mainimport ( "context" "fmt" "github.com/tencentyun/cos-go-sdk-v5" "net/http" "net/url" "sort" "time")// 请替换上面的假如值为理论的 SecretId、SecretKey、BucketName 和 Region。const ( SecretId = "xxxxxx" SecretKey = "xxx" BucketName = "xxxxx" // 例如 "example-1250000000" BucketRegion = "ap-shanghai" // 例如 "ap-guangzhou")// 创立 COS 客户端func createCOSClient(secretId, secretKey, bucketName, bucketRegion string) *cos.Client { u, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", bucketName, bucketRegion)) b := &cos.BaseURL{BucketURL: u} client := cos.NewClient(b, &http.Client{ Transport: &cos.AuthorizationTransport{ SecretID: secretId, SecretKey: secretKey, }, }) return client}func getLastUpdatedFileInfo(client *cos.Client) (key, lastModifiedTime string, err error) { c := context.Background() // 初始化一个空字符串,示意从桶的结尾获取文件列表 nextMarker := "" var allContents []cos.Object for { opt := &cos.BucketGetOptions{ MaxKeys: 1000, Marker: nextMarker, } v, _, err := client.Bucket.Get(c, opt) if err != nil { return "", "", err } allContents = append(allContents, v.Contents...) // 如果没有更多的文件,则进行循环 if !v.IsTruncated { break } // 更新 nextMarker 为下一页的开始地位 nextMarker = v.NextMarker } // 对所有后果进行排序以找到最新更新的对象 if len(allContents) > 0 { sort.Slice(allContents, func(i, j int) bool { ti, errTi := time.Parse(time.RFC3339, allContents[i].LastModified) tj, errTj := time.Parse(time.RFC3339, allContents[j].LastModified) if errTi != nil || errTj != nil { fmt.Printf("Error parsing time: %v, %v", errTi, errTj) return false } return ti.After(tj) }) lastUpdatedObj := allContents[0] return lastUpdatedObj.Key, lastUpdatedObj.LastModified, nil } else { return "", "", fmt.Errorf("桶中没有文件") }}func main() { client := createCOSClient(SecretId, SecretKey, BucketName, BucketRegion) key, lastModifiedTime, err := getLastUpdatedFileInfo(client) if err != nil { fmt.Printf("\n查问失败: %v\n", err) return } fmt.Printf("\n最初更新的文件:\n") fmt.Printf("文件门路: %s\n", key) fmt.Printf("最初批改工夫: %s\n", lastModifiedTime)}
运行main.go
go run main.go
注:为了验证代码有效性,我这里前面又加了一个新的文件:zaZTYa1i2x.txt
加个进度条
下面的代码曾经能够失常满足需要了,然而我新加一个进度条,显示查问了多少文件了。也能大略晓得一个进度的情况,持续批改一下main.go
package mainimport ( "context" "fmt" "github.com/tencentyun/cos-go-sdk-v5" "net/http" "net/url" "sort" "time")// 请替换上面的假如值为理论的 SecretId、SecretKey、BucketName 和 Region。const ( SecretId = "xxxx" SecretKey = "xxxxx" BucketName = "xxxxx" // 例如 "example-1250000000" BucketRegion = "ap-shanghai" // 例如 "ap-guangzhou")// 创立 COS 客户端func createCOSClient(secretId, secretKey, bucketName, bucketRegion string) *cos.Client { u, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", bucketName, bucketRegion)) b := &cos.BaseURL{BucketURL: u} client := cos.NewClient(b, &http.Client{ Transport: &cos.AuthorizationTransport{ SecretID: secretId, SecretKey: secretKey, }, }) return client}func getLastUpdatedFileInfo(client *cos.Client) (key, lastModifiedTime string, err error) { c := context.Background() nextMarker := "" var allContents []cos.Object var retrievedCount int fmt.Println("开始检索文件列表...") for { opt := &cos.BucketGetOptions{ MaxKeys: 10000, Marker: nextMarker, } v, _, err := client.Bucket.Get(c, opt) if err != nil { return "", "", err } retrievedCount += len(v.Contents) fmt.Printf("已检索 %d 个文件...\r", retrievedCount) // 输入进度信息 '\r' 会笼罩以后行,这样咱们就能够在同一行更新进度 allContents = append(allContents, v.Contents...) if !v.IsTruncated { break } nextMarker = v.NextMarker } fmt.Println("\n文件列表检索实现。") if len(allContents) > 0 { sort.Slice(allContents, func(i, j int) bool { ti, errTi := time.Parse(time.RFC3339, allContents[i].LastModified) tj, errTj := time.Parse(time.RFC3339, allContents[j].LastModified) if errTi != nil || errTj != nil { fmt.Printf("Error parsing time: %v, %v", errTi, errTj) return false } return ti.After(tj) }) lastUpdatedObj := allContents[0] return lastUpdatedObj.Key, lastUpdatedObj.LastModified, nil } else { return "", "", fmt.Errorf("桶中没有文件") }}func main() { client := createCOSClient(SecretId, SecretKey, BucketName, BucketRegion) key, lastModifiedTime, err := getLastUpdatedFileInfo(client) if err != nil { fmt.Printf("\n查问失败: %v\n", err) return } fmt.Printf("\n最初更新的文件:\n") fmt.Printf("文件门路: %s\n", key) fmt.Printf("最初批改工夫: %s\n", lastModifiedTime)}
运行main.go
go run main.go
持续欠缺
持续欠缺一下代码:我须要把MaxKeys 提取进去,减少一下输入程序的运行工夫,并把输入文件的工夫戳调整为东八区工夫:
package mainimport ( "context" "fmt" "github.com/tencentyun/cos-go-sdk-v5" "net/http" "net/url" "sort" "time")const ( SecretId = "xxxx" SecretKey = "xxxxx" BucketName = "xxxxx" BucketRegion = "ap-shanghai" MaxKeys = 1000 // 设置最大检索数量的常量)var cstZone = time.FixedZone("CST", 8*3600) // 东八区时区func createCOSClient(secretId, secretKey, bucketName, bucketRegion string) *cos.Client { u, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", bucketName, bucketRegion)) b := &cos.BaseURL{BucketURL: u} client := cos.NewClient(b, &http.Client{ Transport: &cos.AuthorizationTransport{ SecretID: secretId, SecretKey: secretKey, }, }) return client}func getLastUpdatedFileInfo(client *cos.Client) (key, lastModifiedTime string, err error) { c := context.Background() nextMarker := "" var allContents []cos.Object var retrievedCount int fmt.Println("开始检索文件列表...") for { opt := &cos.BucketGetOptions{ MaxKeys: MaxKeys, // 应用常量 MaxKeys Marker: nextMarker, } v, _, err := client.Bucket.Get(c, opt) if err != nil { return "", "", err } retrievedCount += len(v.Contents) fmt.Printf("已检索 %d 个文件...\r", retrievedCount) allContents = append(allContents, v.Contents...) if !v.IsTruncated { break } nextMarker = v.NextMarker } fmt.Println("\n文件列表检索实现。") if len(allContents) > 0 { sort.Slice(allContents, func(i, j int) bool { ti, errTi := time.Parse(time.RFC3339, allContents[i].LastModified) tj, errTj := time.Parse(time.RFC3339, allContents[j].LastModified) if errTi != nil || errTj != nil { fmt.Printf("Error parsing time: %v, %v", errTi, errTj) return false } return ti.After(tj) }) lastUpdatedObj := allContents[0] // 将文件的 LastModified 工夫字符串转换为 time.Time t, err := time.Parse(time.RFC3339, lastUpdatedObj.LastModified) if err != nil { return "", "", fmt.Errorf("无奈解析最初批改工夫: %v", err) } // 转换为东八区工夫 cstTime := t.In(cstZone).Format(time.RFC3339) return lastUpdatedObj.Key, cstTime, nil } else { return "", "", fmt.Errorf("桶中没有文件") }}func main() { start := time.Now() // 程序开始工夫 client := createCOSClient(SecretId, SecretKey, BucketName, BucketRegion) key, lastModifiedTime, err := getLastUpdatedFileInfo(client) if err != nil { fmt.Printf("\n查问失败: %v\n", err) return } fmt.Printf("\n最初更新的文件:\n") fmt.Printf("文件门路: %s\n", key) fmt.Printf("最初批改工夫: %s\n", lastModifiedTime) elapsed := time.Since(start) // 程序执行工夫 fmt.Printf("\n程序运行工夫: %s\n", elapsed)}
运行批改后的main.go文件:
go run main.go
持续发散
持续发散一下,我须要输入最初上传的10个文件
package mainimport ( "context" "fmt" "github.com/tencentyun/cos-go-sdk-v5" "net/http" "net/url" "sort" "time")// 请替换上面的假如值为理论的 SecretId、SecretKey、BucketName 和 Region。const ( SecretId = "AKID7Mhwz45A9zqcCf4s07A7FIKKTlAiEf7M" SecretKey = "KXbXL0unr2EaBsicYejj1GkEjO2jWOAg" BucketName = "layabox-10028350" // 例如 "example-1250000000" BucketRegion = "ap-shanghai" // 例如 "ap-guangzhou" MaxKeys = 1000 // 设置最大检索数量的常量 NumberOfFiles = 10 // 须要获取的最初更新的文件数量)var cstZone = time.FixedZone("CST", 8*3600) // 东八区时区func createCOSClient(secretId, secretKey, bucketName, bucketRegion string) *cos.Client { u, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", bucketName, bucketRegion)) b := &cos.BaseURL{BucketURL: u} client := cos.NewClient(b, &http.Client{ Transport: &cos.AuthorizationTransport{ SecretID: secretId, SecretKey: secretKey, }, }) return client}func getLastUpdatedFileInfo(client *cos.Client, numberOfFiles int) ([]cos.Object, error) { c := context.Background() nextMarker := "" var allContents []cos.Object var retrievedCount int fmt.Println("开始检索文件列表...") for { opt := &cos.BucketGetOptions{ MaxKeys: MaxKeys, // 应用常量 MaxKeys Marker: nextMarker, } v, _, err := client.Bucket.Get(c, opt) if err != nil { return nil, err } retrievedCount += len(v.Contents) fmt.Printf("已检索 %d 个文件...\r", retrievedCount) allContents = append(allContents, v.Contents...) if !v.IsTruncated { break } nextMarker = v.NextMarker } fmt.Println("\n文件列表检索实现。") fmt.Printf("\n桶中总文件数: %d\n", len(allContents)) if len(allContents) > 0 { sort.Slice(allContents, func(i, j int) bool { ti, errTi := time.Parse(time.RFC3339, allContents[i].LastModified) tj, errTj := time.Parse(time.RFC3339, allContents[j].LastModified) if errTi != nil || errTj != nil { fmt.Printf("Error parsing time: %v, %v", errTi, errTj) return false } return ti.After(tj) }) // 截取切片以获取最初更新的numberOfFiles个文件 if len(allContents) > numberOfFiles { allContents = allContents[:numberOfFiles] } // 返回最初更新的numberOfFiles个文件 return allContents, nil } else { return nil, fmt.Errorf("桶中没有文件") }}func main() { start := time.Now() // 程序开始工夫 client := createCOSClient(SecretId, SecretKey, BucketName, BucketRegion) files, err := getLastUpdatedFileInfo(client, NumberOfFiles) if err != nil { fmt.Printf("\n查问失败: %v\n", err) return } fmt.Printf("\n最初更新的%d个文件:\n", NumberOfFiles) for _, file := range files { t, err := time.Parse(time.RFC3339, file.LastModified) if err != nil { fmt.Printf("无奈解析文件 %s 的最初批改工夫: %v\n", file.Key, err) continue } cstTime := t.In(cstZone).Format(time.RFC3339) fmt.Printf("文件门路: %s\n", file.Key) fmt.Printf("最初批改工夫: %s\n", cstTime) } elapsed := time.Since(start) // 程序执行工夫 fmt.Printf("\n程序运行工夫: %s\n", elapsed)}
其实也想过协程或者其余形式?然而奈何max-keys 最大是1000测试了一下没有太大的晋升放弃了......
总结
在这篇博客中,咱们学习了如何应用腾讯云 COS Go SDK 查问存储桶中最新的文件信息。这包含如何创立COS客户端,如何逐页检索对象列表,并如何对后果排序以找到最初更新的对象。咱们还展现了如何优化用户体验,通过实时进度更新和检索多个文件来改良程序。
心愿本文能帮忙你在应用腾讯云 COS 时实现更高效的数据管理。