首先在控制台配置好oss bucket, 跨域允许, 获取access_key和access_secret

OSS_END_POINT="oss-cn-hongkong.aliyuncs.com"
OSS_ACCESS_KEY_ID="access_key"
OSS_ACCESS_KEY_SECRET="access_secret"
OSS_BUCKET="bucket_name"

后端接口 /upload/token 负责生成签名地址,这里选择前端拿到接口上传,方便显示上传进度

// router/router.go
r.POST("upload/token", api.UpLoadToOSS)

// api/upload.go
func UpLoadToOSS(c *gin.Context)  {
    var service services.UpLoadToOSSService
    if err := c.ShouldBind(&service); err != nil {
        c.JSON(200, err.Error())
    } else {
        res := service.UpLoad()
        c.JSON(200, res)
    }
}

// service/upload_token_service.go
type UpLoadToOSSService struct {
    FileName string `form:"filename" json:"filename" binding:"required"`
}

func (service *UpLoadToOSSService) UpLoad() *serializers.Response {
       // 新建客户端
    client, err := oss.New(os.Getenv("OSS_END_POINT"), 
os.Getenv("OSS_ACCESS_KEY_ID"), os.Getenv("OSS_ACCESS_KEY_SECRET"))
    if err != nil {
        return &serializers.Response{
            Status:e.OSS_CONFIG_ERROR,
            Message:e.GetMsg(e.OSS_CONFIG_ERROR),
            Error:err.Error(),
        }
    }

    // 获取存储空间
    bucket, err := client.Bucket(os.Getenv("OSS_BUCKET"))
    if err != nil {
        return &serializers.Response{
            Status:e.OSS_CONFIG_ERROR,
            Message:e.GetMsg(e.OSS_CONFIG_ERROR),
            Error:err.Error(),
        }
    }

    // 获取扩展名
    ext := filepath.Ext(service.FileName)

    // 带可选参数的签名直传
    options := []oss.Option{
        oss.ContentType(mime.TypeByExtension(ext)),
    }
        
    key := "upload/video/" + uuid.Must(uuid.NewRandom()).String() + ext
    // 生成签名url, 签名直传
    signedPutURL, err := bucket.SignURL(key, oss.HTTPPut, 600, options...)
    if err != nil {
        return &serializers.Response{
            Status:e.OSS_CONFIG_ERROR,
            Message:e.GetMsg(e.OSS_CONFIG_ERROR),
            Error:err.Error(),
        }
    }

    // 查看视频
    signedGetURL, err := bucket.SignURL(key, oss.HTTPGet, 600)
    if err != nil {
        return &serializers.Response{
            Status:e.OSS_CONFIG_ERROR,
            Message:e.GetMsg(e.OSS_CONFIG_ERROR),
            Error:err.Error(),
        }
    }

    return &serializers.Response{
        Data: map[string]string{
            "key": key,
            "put": signedPutURL,
            "get": signedGetURL,
        },
    }
}

接口返回:


image.png

前端请求到put_url发送put请求上传, get_url查看视频
https://github.com/xianxuhua/vue-ele-upload-video
这个封装上传视频比较友好,但是重写了http-request方法后和官网一样不能显示上传进度
可以在vue-ele-upload-video源代码里添加props, 去掉data return 中的videoUploadPercent

image.png

然后前端调用
            <EleUploadVideo
                action=""
                v-model="videoUrl"
                :http-request="UploadVideo"
                :videoUploadPercent="videoUploadPercent"
              >
                <i class="el-icon-upload"></i>
                <div class="el-upload__text"><em>点击上传</em></div>
              </EleUploadVideo>
import EleUploadVideo from 'vue-ele-upload-video'

components: {
      EleUploadVideo,
},
data() {
    return {
        videoUploadPercent: 0,
        videoUrl: "",
    }
},
methods: {
    UploadVideo(option) {
       // 获取签名后的上传地址
        axios.post("/upload/token", {
          filename: option.file.name,
        }).then(rep => {
          const Req = new XMLHttpRequest();
          // put 请求上传文件
          Req.open('PUT', rep.data.data.put, true);
          // 计算上传进度
          Req.upload.addEventListener("progress", (e)=> {
            if (e.lengthComputable) {
              this.videoUploadPercent = Math.floor(e.loaded / e.total * 100);
            }
          }, false);
          // 上传完成
          Req.onload = () => {
            this.videoUploadPercent = 0;
            this.videoUrl = rep.data.data.get;
          };
          // 上传
          Req.send(option.file);
        })
      },
}

image.png

image.png

如果做多文件上传可以考虑使用golang并发上传

有疑问加站长微信联系(非本文作者)