Go gin上传文件到oss

依赖包:

  • gin go get -u github.com/gin-gonic/gin
  • oss go get github.com/aliyun/aliyun-oss-go-sdk/oss

参考文档:

源代码

package main

import (
	"fmt"

	"github.com/gin-gonic/gin"
	"x-dcm/internal/pkg/logic/ossl"
	"x-dcm/internal"
	"x-dcm/internal/app/router"
	"x-dcm/internal/pkg/conf"
)

func init() {
    conf.MustInitConf()
    dal.MustInitOss()
}

func main() {

	r := gin.New()

    //解决跨域中间件
	r.Use(middleware.Cors())
    
    //路由
	api := r.Group("/api")
    
    user := api.Group("/user").Use(middleware.Auth())
	user.POST("/upload", OssUpload)
	
	if err := r.Run(fmt.Sprintf(":%d", conf.Conf.Http.Port)); err != nil {
		panic(fmt.Errorf("httpServer run fail: %w", err))
	}
}

func OssUpload(ctx *gin.Context) {
	userID := ctx.GetInt("user_id")
	file, err := ctx.FormFile("filed")
	if err != nil {
		response.Fail(ctx, errno.ErrFileFail, err.Error(), nil)
		return
	}

	putFile, err := ossl.PutFile(file)
	if err != nil {
		response.Fail(ctx, errno.ErrParam, err.Error(), nil)
		return
	}

	fmt.Println(userID, fType, file.Filename, file.Header.Get("Content-Type"))

	response.Success(ctx, putFile)
	return
}
oss:
  id: 'your_key_id'
  secret: 'your_key_secret'
  endpoint: "https://oss-cn-beijing.aliyuncs.com"
  bucket: "your_bucket"
  domain: "https://img.cdn.xxx.cn"
package conf

import (
	"flag"
	"fmt"
	"github.com/spf13/viper"
)

var Conf Config

type Config struct {
	Oss        Oss        `yaml:"oss"`
}

type Oss struct {
	Id       string `yaml:"id"`
	Secret   string `yaml:"secret"`
	Endpoint string `yaml:"endpoint"`
	Bucket   string `yaml:"bucket"`
	Domain   string `yaml:"domain"`
}

type FType struct {
	Key    string   `json:"key"`
	Name   string   `json:"name"`
	Path   string   `json:"path"`
	Suffix []string `json:"suffix"`
}

// MustInitConf 初始化配置文件
func MustInitConf() {
	var configFile string
	flag.StringVar(&configFile, "c", "./configs/local.yaml", "your app config file.")
	if !flag.Parsed() {
		flag.Parse()
	}

	viper.SetConfigFile(configFile)
	viper.SetConfigType("yaml")

	// Find and read the config file
	if err := viper.ReadInConfig(); err != nil {
		panic(fmt.Errorf("fatal error config file: %w", err))
	}

	//Unmarshal 将配置解组为 Struct。确保正确设置结构字段上的标签。
	if err := viper.Unmarshal(&Conf); err != nil {
		panic(fmt.Errorf("unmarshal error config file: %w", err))
	}

	fmt.Println("config initialized")
}
package dal

import (
	"x-dcm/internal/pkg/conf"
	"fmt"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
)

var (
	cliOss *oss.Client
)

func MustInitOss() {
	var err error
	c := conf.Conf
	cliOss, err = oss.New(c.Oss.Endpoint, c.Oss.Id, c.Oss.Secret,
		oss.EnableCRC(true),  //强烈建议您不要关闭CRC数据校验功能。如果您关闭此功能,则阿里云不保证上传、下载过程数据的完整性。
		oss.Timeout(10, 120), //oss.Timeout(10, 120)表示设置HTTP连接超时时间为10秒(默认值为30秒),HTTP读写超时时间为120秒(默认值为60秒)。0表示永不超时(不推荐使用)。
	)
	if err != nil {
		panic(fmt.Errorf("fatal error oss init: %w", err))
	}

	//获取默认桶
	_, err = cliOss.Bucket(c.Oss.Bucket)
	if err != nil {
		panic(fmt.Errorf("fatal error oss init create bucket: %w", err))
	}
}

func GetOss() *oss.Client {
	return cliOss
}

func DefaultBucket() string {
	return conf.Conf.Oss.Bucket
}

package ossl

import (
	"x-dcm/internal/pkg/biz/tools"
	"x-dcm/internal/pkg/conf"
	"x-dcm/internal/pkg/dal"
	"errors"
	"fmt"
	"mime/multipart"
	"path"
	"time"
)

type PutFileResp struct {
	OriginName    string `json:"origin_name"`
	OriginUri     string `json:"origin_uri"`
	OriginFullUri string `json:"origin_full_uri"`
	LocalName     string `json:"local_name"`
}

func PutFile(fileHeader *multipart.FileHeader) (*PutFileResp, error) {

    //生成路径
	c.Path = fmt.Sprintf("upload/user/%v/avatar", userID)
    
	//获取文件的后缀(文件类型) .jpg
	fileSuffix := path.Ext(fileHeader.Filename)

    //生成上传oss的完整地址
	originFileName := fmt.Sprintf("%v%v%v", FastMD5(fileHeader.Filename), time.Now().Format("05"), fileSuffix)
	originFilePath := fmt.Sprintf("%v/%v", c.Path, originFileName)

    //获取默认桶
	ossCli := dal.GetOss()
	bucket, err := ossCli.Bucket(dal.DefaultBucket())
	if err != nil {
		return nil, err
	}
	//
	fd, err := fileHeader.Open()
	if err != nil {
		return nil, err
	}
	defer fd.Close()

	//上传
	err = bucket.PutObject(originFilePath, fd)
	if err != nil {
		return nil, err
	}

	result := PutFileResp{
		OriginName:    originFileName,
		OriginFullUri: fmt.Sprintf("%v/%v", conf.Conf.Oss.Domain, originFilePath),
		OriginUri:     originFilePath,
		LocalName:     fileHeader.Filename,
	}
	return &result, nil
}

//FastMD5 生成md5
func FastMD5(str string) string {
	h := md5.New()
	h.Write([]byte(str))
	return hex.EncodeToString(h.Sum(nil))
}
{
	"code": 10000,
	"msg": "成功",
	"data": {
		"origin_name": "cc55299bebb3a767cacc875fe748105947.jpg",
		"origin_uri": "upload/user/213225/avatar/cc55299bebb3a767cacc875fe748105947.jpg",
		"origin_full_uri": "https://img.cdn.xx.cn/upload/user/213225/avatar/cc55299bebb3a767cacc875fe748105947.jpg",
		"local_name": "wasa-crispbread-rR2YntJJOl4-unsplash.jpg"
	},
	"time": 1665413987
}

你可能感兴趣的:(Go修罗场,golang,gin,开发语言)