首先在控制台配置好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,
},
}
}
接口返回:
前端请求到put_url发送put请求上传, get_url查看视频
https://github.com/xianxuhua/vue-ele-upload-video
这个封装上传视频比较友好,但是重写了http-request方法后和官网一样不能显示上传进度
可以在vue-ele-upload-video源代码里添加props, 去掉data return 中的videoUploadPercent
然后前端调用
<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);
})
},
}
如果做多文件上传可以考虑使用golang并发上传
参考:https://github.com/Gourouting/giligili/blob/master/service/upload_token_service.go
https://github.com/xianxuhua/vue-ele-upload-video
有疑问加站长微信联系(非本文作者)