前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >个人使用腾讯云Cos上传文件功能优化思路分享

个人使用腾讯云Cos上传文件功能优化思路分享

原创
作者头像
陈杪秋
修改2024-03-07 16:50:07
2860
修改2024-03-07 16:50:07

前言

近期笔者在写一个网盘项目时需要使用到腾讯云的cos功能,由于财力不足,不得不对用户的上传功能进行优化,以免一觉睡醒,cos欠费

以下是笔者优化的思路主要为md5码优化redis优化,以消耗请求次数的方法优化cos存储容量。

MD5码优化上传

将用户文件名以md5码的格式上传至腾讯云进行存储。在用户上传文件时,计算文件内容的md5码,将其与文件名后缀结合上传至腾讯云cos。

MD5码计算方式参考

代码语言:go
复制
// GetFileMD5 使用本地文件路径计算本地文件md5码
func GetFileMD5(filePath string) (string, error) {
	file, err := os.Open(filePath)
	defer func() {
		_ = file.Close()
	}()
	if err != nil {
		return "", err
	}
	hash := md5.New()
	// 如果一个文件有相同的内容但是后缀不同时,仅计算文件内容得到的md5码是相同的
    // 用户在下载时可能下载到相同内容但是不同后缀的文件,需补上文件后缀计算md5码
	ext := path.Ext(file.Name())
	hash.Write([]byte(ext))
	_, _ = io.Copy(hash, file)
	return hex.EncodeToString(hash.Sum(nil)), nil
}

在随后用户再次上传相同类型文件时,先使用腾讯云的接口判断文件是否上传过用户文件夹,如上传过则放弃上传。

上传接口参考

代码语言:go
复制
// 此处使用简单上传对象接口进行上传
func (cloud *TencentCloudDisk) UploadSimpleFile(localFilePath string, userId string, md5 string, fileSize int64) error {
    // 判断文件大小,简单接口最大仅支持5GB数据
	if fileSize/1024/1024/1024 > 1 {
		return fmt.Errorf("file to big, please use uploadfile")
	}

	// 调用腾讯云提供的接口检查是否上传过该文件
	extend := path.Ext(localFilePath)
	ok, err := cloud.IsObjectExist(userId, "", md5+extend)
	if err != nil {
		return err
	}

    // 如果不存在,则直接调用接口上传
	if !ok {
		key := fastBuildKey(userId, "", md5+extend)
		if err = cloud.uploadSimpleFile(localFilePath, key); err != nil {
			return err
		}
	}

	return nil
}

检查文件是否在云端接口参考

代码语言:go
复制
func (cloud *TencentCloudDisk) checkObjectIsExist(key string) (bool, error) {
    // 使用	bucketname,secretId,secretKey生成默认client
	client := cloud.getDefaultClient()
    // 调用腾讯云接口
	ok, err := client.Object.IsExist(context.Background(), key)
	if err != nil {
		return false, err
	}
	return ok, nil
}

// IsObjectExist 快速构建key调用接口查询
func (cloud *TencentCloudDisk) IsObjectExist(userId string, filePath string, fileName string) (bool, error) {
	key := fastBuildKey(userId, filePath, fileName)
	ok, err := cloud.checkObjectIsExist(key)
	return ok, err
}

简单上传接口参考

代码语言:go
复制
func (cloud *TencentCloudDisk) uploadSimpleFile(localFilePath string, key string) error {
	client := cloud.getDefaultClient()
	opt := &cos.ObjectPutOptions{
		ObjectPutHeaderOptions: &cos.ObjectPutHeaderOptions{
			ContentDisposition: "attachment", // 添加上这段时调用getobject 默认下载
		},
	}
    // 使用官方api接口
	_, err := client.Object.PutFromFile(context.Background(), key, localFilePath, opt)
	if err != nil {
		return err
	}
	return nil
}

构建结构体参考

代码语言:go
复制
type TencentCloudDisk struct {
	bucketname string
	secretId   string
	secretKey  string
}

func (cloud *TencentCloudDisk) getDefaultClient() *cos.Client {
	u, _ := url.Parse(cloud.bucketname)
	b := &cos.BaseURL{BucketURL: u}
	c := cos.NewClient(b, &http.Client{
		Transport: &cos.AuthorizationTransport{
			SecretID:  cloud.secretId,
			SecretKey: cloud.secretKey,
		},
	})
	return c
}

Redis优化文件上传

在上传文件时遇到重复文件时仍需调用腾讯云接口,如果想要少调用远程接口可以使用redis。

使用redis记录上传文件的md5码,将多个用户上传的相同文件索引至相同的云文件,避免重复上传。同时方便后续管理员进行文件封禁。

使用redis优化参考

代码语言:go
复制
//计算文件md5码
md5String, err := GetFileMD5(dst)
if err != nil {
    return serializer.ParamsErr("file err", err)
}

// 使用md5码查询redis近期是否上传文件,如果上传过对应文件则直接跳过腾讯云查询
filePath := GetFileInfoFromRedis(md5String)
if filePath == "" {
    // 近期没有人调用过该文件,上传至云服务器
    err = disk.BaseCloudDisk.UploadSimpleFile(dst, userId, md5String, file.Size)
    if err != nil {
        return serializer.DBErr("can't upload to cloud", err)
    }
    filePath = userId
}
.... 
// 保存文件信息到redis
SaveFileUploadInfoToRedis()

Redis保存文件信息参考,以go-redis为例

代码语言:go
复制
// 生成对应key
func FileInfoStoreKey(id string) string {
	return fmt.Sprintf("file:cloud:%s", id)
}

// 保存文件
func SaveFileUploadInfoToRedis() {
    // 随机过期时间,减少缓存雪崩几率
	randTime := time.Hour*12 + time.Minute*time.Duration(rand.Intn(60))
	cache.RedisClient.Set(context.Background(), cache.FileInfoStoreKey(file.FileUuid), file.FilePath, randTime)
}

获取redis文件

代码语言:go
复制
func GetFileInfoFromRedis(md5 string) string {
	filePath := cache.RedisClient.Get(context.Background(), cache.FileInfoStoreKey(md5)).Val()
	return filePath
}

结尾

感谢你看到这里,如果这篇文章对你有帮助的话不妨点个赞,期待下次再见。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • MD5码优化上传
  • Redis优化文件上传
  • 结尾
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档