乐趣区

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

背景:

腾讯云账号下,有很多对象存储 COS 桶:

我当初想确认某一个对象存储桶的沉闷水平,简略的来说。我想晓得这个桶外面最初上传的一个文件是什么,以及它的上传工夫戳。
本文将介绍如何应用腾讯云对象存储(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

第一版代码:

应用 chatgpt 生成第一版代码:
main.go

package main

import (
    "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 main

import (
    "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 main

import (
    "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 main

import (
    "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 main

import (
    "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 main

import (
    "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 时实现更高效的数据管理。

退出移动版