使用腾讯云go sdk 查询对象存储中最新文件

背景:

腾讯云账号下,有很多对象存储COS桶:
image.png
我现在想确认某一个对象存储桶的活跃程度,简单的来说。我想知道这个桶里面最后上传的一个文件是什么,以及它的上传时间戳。
本文将介绍如何使用腾讯云对象存储(COS)的 Go 语言 SDK 查询指定存储桶中的最新文件信息,包括文件路径和上传时间。本教程假设读者已经具备基本的 Go 语言编程知识,并且对腾讯云 COS 有一定的了解。

使用腾讯云go sdk 查询对象存储中最新文件

前置条件

  • 您需要拥有一个腾讯云账号,并创建了至少一个COS存储桶。
  • 了解Go语言和基本的并发编程知识。
  • 确保您已安装Go运行时环境。

安装腾讯云COS Go SDK

在开始之前,先确保您的开发环境已安装了腾讯云COS的Go SDK。如果尚未安装,可以使用以下Go命令安装:

mkdir xxxx
go mod int xxxx
go get github.com/tencentyun/cos-go-sdk-v5

我们这里的操作是属于List Object 参照:GetBucket
image.png

第一版代码:

使用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

image.png
运行后也许感觉是正确的,毕竟没有报错。但是这里是有问题的,为什么呢?因为我本身不知道最后一个文件是什么,我手动上传了一个文件,最后一个文件应该是输出:go1.22.0.linux-amd64.tar.gz!
image.png
什么原因呢?问题应该是在这里:

	c := context.Background()opt := &cos.BucketGetOptions{MaxKeys: 1000, // 修改这个值以获取更多或更少的对象}

image.png
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.ObjectisTruncated := truenextMarker := ""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.IsTruncatednextMarker = 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

image.png
输出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.Objectfor {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

image.png
注:为了验证代码有效性,我这里后面又加了一个新的文件: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.Objectvar retrievedCount intfmt.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

image.png

继续完善

继续完善一下代码:我需要把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.Objectvar retrievedCount intfmt.Println("开始检索文件列表...")for {opt := &cos.BucketGetOptions{MaxKeys: MaxKeys, // 使用常量 MaxKeysMarker:  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.Timet, 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

image.png

继续发散

继续发散一下,我需要输出最后上传的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.Objectvar retrievedCount intfmt.Println("开始检索文件列表...")for {opt := &cos.BucketGetOptions{MaxKeys: MaxKeys, // 使用常量 MaxKeysMarker:  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)
}

image.png
其实也想过协程或者其他方式?但是奈何max-keys 最大是1000测试了一下没有太大的提升放弃了…

总结

在这篇博客中,我们学习了如何使用腾讯云 COS Go SDK 查询存储桶中最新的文件信息。这包括如何创建COS客户端,如何逐页检索对象列表,并如何对结果排序以找到最后更新的对象。我们还展示了如何优化用户体验,通过实时进度更新和检索多个文件来改进程序。

希望本文能帮助你在使用腾讯云 COS 时实现更高效的数据管理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/496679.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计讯物联5G RedCap网关TG463化繁为简,推动5G赋能千行百业

5G RedCap,全称为Reduced Capability,即在5G的基础上,对部分功能进行化繁为简后形成的新技术标准,故又称轻量化5G。作为高性价比下的精简技术,5G RedCap技术具备成本低、低功耗、兼顾5G等特点,能够在确保应…

东方博宜 1062. 求落地次数

东方博宜 1062. 求落地次数 #include<iostream> using namespace std; int main() {int n 100 ;double m n / 2.0 ;int cnt 1 ;while(m>0.5){m m / 2.0 ;cnt 1;}cout << cnt ;return 0 ; }

【Linux】云服务器的Redis被黑

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;Linux ⛺️稳中求进&#xff0c;晒太阳 攻击发现&#xff1a; 这个异常情况是在腾讯云被入侵后&#xff0c;短信提醒发现的。并没有系统的学习过关于服务器安防相关的知识&#xff0c;遇到…

nginx 第三方模块 与变量

一&#xff0c; 网页的状态页 详细见上一章 《nginx 配置文件详细介绍》 二&#xff0c;Nginx 第三方模块 开源 不是官方模块 别人写的 你编译进nginx&#xff08;./configure 这一步添加的模块&#xff09; &#xff08;一&#xff09;ehco 模块 这边以echo 模块为…

DVWA 靶场之 Command Injection(命令执行)middlehigh

对于 middle 难度的 我们直接先看源码 <?phpif( isset( $_POST[ Submit ] ) ) {// Get input$target $_REQUEST[ ip ];// Set blacklist$substitutions array(&& > ,; > ,);// Remove any of the characters in the array (blacklist).$target str_rep…

若依前后端分离版开源项目学习

前言&#xff1a;vscode中vue代码没有高亮显示&#xff0c;可以下载vetur插件解决&#xff0c;ctrl点击无法跳转函数定义问题&#xff0c;可以下载vue-helper插件解决&#xff1b;idea中ctrl点击函数即可跳转函数定义。 一、登录 1.生成验证码 基本思路&#xff1a; 后端生…

探索 SPA 与 MPA:前端架构的选择与权衡

查看本专栏目录 关于作者 还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#x…

哪里申请EV代码签名证书?

EV代码签名证书是一种高级别的数字证书&#xff0c;它通过严格的验证流程&#xff0c;确保软件发布者身份的真实性和可信度。相较于普通代码签名证书&#xff0c;EV证书采用了更严格的验证标准&#xff0c;包括对企业身份、法律地位、组织结构多个方面的核实。这使得EV证书成为…

ROS 2基础概念#1:计算图(Compute Graph)| ROS 2学习笔记

在ROS中&#xff0c;计算图&#xff08;ROS Compute Graph&#xff09;是一个核心概念&#xff0c;它描述了ROS节点之间的数据流动和通信方式。它不仅仅是一个通信网络&#xff0c;它也反映了ROS设计哲学的核心——灵活性、模块化和可重用性。通过细致探讨计算图的高级特性和实…

JavaScript最新实现城市级联操作,json格式的数据

前置知识&#xff1a; <button onclick"doSelect()">操作下拉列表</button><hr>学历&#xff1a;<select id"degree"><option value"0">--请选择学历--</option><option value"1">专科<…

峟思工程仪器仪表:高精度测缝计助力工程安全

随着科技的不断进步&#xff0c;工程测量领域对于设备的精度和可靠性要求越来越高。在这一背景下&#xff0c;峟思工程仪器仪表品牌的测缝计凭借其卓越的性能和广泛的应用领域&#xff0c;成为了工程测量领域中的佼佼者。 测缝计作为一种关键的工程监测设备&#xff0c;主要用于…

【经验】vscode 鼠标拖曳不能选中整行文字,只能选中纵向矩形范围

1、问题描述 不知道昨天操作vscode设置界面时&#xff0c;误选择了啥&#xff0c;导致鼠标拖曳不能选中整行文字&#xff0c;只能选中纵向矩形范围&#xff0c;现象如下&#xff1a; 2、解决方法 1&#xff09;打开设置界面 点击左下角按键&#xff0c;选择“设置” 2&…