如何使用Go提供http部分内容? [英] How to serve http partial content with Go?

查看:99
本文介绍了如何使用Go提供http部分内容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个网页服务器,我正在提供一些来自不同来源(本地,其他服务器,S3)的音频文件。我希望为这些文件启用部分内容,以便HTML音频标签能够搜索并循环播放。



我该如何执行此操作?我知道 http 包中的 ServeContent 函数可以做到这一点,但我该如何通过自己提供文件来做到这一点?我不需要这样做,这样我就可以使用同一个处理程序来处理来自不同源的文件。 解决方案

提供部分内容为不平凡的。请参阅wikipedia上的字节服务以获取简介。你必须处理特定的状态代码和标题(包括请求和响应),这并不难,但你不应该浪费你的时间做这件事。



如果要投放(或投放)的内容是一个文件,您可以使用 http .ServeFile() 就像你提到的那样,它处理提供部分内容(范围请求)。



如果内容是服务不作为文件存在,则 http.ServeContent() code> 是你的朋友:

  func ServeContent(w ResponseWriter,req * Request,
name name string,modtime time.Time,content io.ReadSeeker)

是的,它也处理服务部分内容(范围请求):


ServeContent比io.Copy的主要优点在于它可以正确处理Range请求,se ts的MIME类型,并处理If-Modified-Since请求。

您只需提供 io.ReadSeeker 查看您的内容,这是这是为了使实现可以跳转到客户请求的部分,即需要服务的部分。您可能会问:如何做到这一点?



bytes 包中包含一个实现 io.ReadSeeker 的类型: bytes.Reader

<例如,如果你的内容是 [] byte ,你可以获得一个 io.ReadSeeker 这个:

  var content [] byte 
//填充内容
r:= bytes.NewReader(content )

如果您没有将整个内容作为 [ ]字节?一种选择是提供一个实现 io.ReadSeeker 的自己类型的值。

io.ReadSeeker 是:

 类型ReadSeeker接口{
读取器
Seeker
}

io.Reader 包含一个方法:

读取(p []字节)(n int,err错误)

io.Seeker 还包含一种方法:

pre code $ Seek(offset int64,whence int)(int64,error)

您的内容在某处可以访问,不知何故,您知道如何。 Seek()被调用来让你知道你的内容需要什么部分(位置),并且 Read()被调用,所以你可以填充传递的切片(以提供实际的内容)。请注意,这些方法可能会被多次调用,因此您必须跟踪您的内容(来源)。如果你选择走这条道路,请阅读链接接口文档,以确保你符合接口的总体合同,以避免出现意外错误。

I have a webserver written in go and I'm serving some audio files from different sources (local, other servers, S3). I want to enable serving partial content for this files so the HTML audio tags are able to seek and loop.

How can I achive this? I know that the http package ServeContent function does this but how can I do it by serving the files myself? I need to do it without this so that I can serve files from different sources with the same handler.

解决方案

Serving partial content is non-trivial. See Byte serving on wikipedia for an introduction. You have to handle specific status codes and headers (both request and response), which is not too hard but you shouldn't waste your time doing that yourself.

If the content to serve (or serve from) is a file, you may use http.ServeFile() just as you mentioned, which handles serving partial content (Range requests).

If the content to be served is not present as a file, then http.ServeContent() is your friend:

func ServeContent(w ResponseWriter, req *Request,
    name string, modtime time.Time, content io.ReadSeeker)

And yes, it also handles serving partial content (Range requests):

The main benefit of ServeContent over io.Copy is that it handles Range requests properly, sets the MIME type, and handles If-Modified-Since requests.

All you need to do is provide an io.ReadSeeker "view" of your content, this is required so that the implementation can "jump" to the part that is requested by the client, the part that needs to be served. You might ask: how to do that?

The bytes package contains a type that implements io.ReadSeeker: bytes.Reader.

So for example if you have the content as a []byte, you may obtain an io.ReadSeeker like this:

var content []byte
// fill content
r := bytes.NewReader(content)

And what if you don't have the whole content as a []byte? One option is to provide a value of your own type that implements io.ReadSeeker.

io.ReadSeeker is:

type ReadSeeker interface {
    Reader
    Seeker
}

io.Reader contains one method:

Read(p []byte) (n int, err error)

io.Seeker also contains one method:

Seek(offset int64, whence int) (int64, error)

Your content is accessible somewhere, somehow, you know how. Seek() is called to let you know what part (position) is required from your content, and Read() is called so you can populate the passed slice (to provide the actual content). Note that these methods may be called multiple times, so you have to keep track where you are in your content (source). If you choose to go down this path, please read the doc of the linked interfaces to make sure you meet the "general contract" of the interfaces to avoid surprise errors.

这篇关于如何使用Go提供http部分内容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆