使用iris实现safari浏览器中使用video标签浏览mp4的功能

sjzwanglong · · 2159 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

  最近在实现一款小程序时,使用到了视频在线播放的功能,由于资金紧张,所以没有采用第三方云存储的方案,而是将视频文件通过文件上传的功能保存在了自己服务器的磁盘上,而查看时,使用iris的sendFile方法将视频文件输入到response中给前台,而这一方法在chrome浏览器中使用video的方法测试没有任何问题,然后发布小程序,在安卓手机上查看也没发现问题,但是在safari上或者iphone手机上查看,则无法播放视频文件,之后在网上查找了一些方法,发现时safari浏览器本身对视频文件的访问策略有自己的方式(通过HttpRequest的Header中Range属性分段获取视频文件),而且网上也给出了相关的解决方法,有java和php的版本,但是没有go语言版本,所以我将自己参考网上的方法使用go+iris的实现方式分享给大家,希望能帮助到大家。代码如下:

func (c *AttachController) GetVideoBy(id uint) {
	if id <= 0 {
		return
	}
	attach, err := c.Service.GetAttachById(id) // 获取数据库中文件的记录
	if err != nil {
		c.Ctx.Application().Logger().Error(err)
	}
	file := attach.FilePath // 获取文件路径
	f, _ := ioutil.ReadFile(file) // 根据文件路径获取文件字节数组

	var reqRange = c.Ctx.Request().Header.Get("Range") // 获取请求头的Range属性值
	var reqBlockRange []string
	if reqRange != "" && strings.HasPrefix(reqRange, "bytes=") {
		reqBlockRange = strings.Split(strings.Split(reqRange, "=")[1], "-")
		c.Ctx.StatusCode(206) // 设置返回状态码,206表示为断点续传
		c.Ctx.ResponseWriter().Header().Set("status", "206")
	}
	fileSize := len(f) // 计算文件字节长度
	startPosition := 0 // 开始读取的位置
	endPosition := 0   // 结束读取的位置
	if reqBlockRange != nil {
		//safari
		startPosition, _ = strconv.Atoi(reqBlockRange[0])
		if len(reqBlockRange) > 1 && reqBlockRange[1] != "" { // 如果Range有截止位置,则将截止位置赋值
			tmp, _ := strconv.Atoi(reqBlockRange[1])
			endPosition = tmp
		} else { // 否则读取全部文件
			// chrome 等
			endPosition = fileSize - 1 
		}
	}

	if reqBlockRange != nil { // 如果safari浏览器时
		if len(reqBlockRange) > 1 && reqBlockRange[1] != "" {
			c.Ctx.ResponseWriter().Header().Set("accept-ranges", "bytes")
			c.Ctx.ResponseWriter().Header().Set("access-control-allow-methods", "HEAD, GET, OPTIONS")
			c.Ctx.ResponseWriter().Header().Set("cache-control", "public, max-age=30726563")
			c.Ctx.ResponseWriter().Header().Set("Content-Type", "video/mp4") // 设置内容类型
			c.Ctx.ResponseWriter().Header().Set("Last-Modified", time.Now().String())
			c.Ctx.ResponseWriter().Header().Set("Connection", "keep-alive")
			c.Ctx.ResponseWriter().Header().Set("content-range", fmt.Sprintf("bytes %d-%d/%d", startPosition, endPosition, fileSize)) // 设置本次读取的范围
			c.Ctx.ResponseWriter().Header().Set("Content-Length", fmt.Sprintf("%d", endPosition-startPosition+1)) // 设置返回的内容长度
			c.Ctx.ResponseWriter().Write(f[startPosition : endPosition+1]) // 截取文件对应的字节位置写入response
		} else { // chrome 等
			c.Ctx.StatusCode(200)
			c.Ctx.SendFile(file, attach.FileDisName)
		}
	} else { // chrome 等
		c.Ctx.StatusCode(200)
		c.Ctx.SendFile(file, attach.FileDisName)
	}
}

 

 


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

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2159 次点击  ∙  1 赞  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传