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

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

问题描述

我有一个用 go 编写的网络服务器,我正在提供来自不同来源(本地、其他服务器、S3)的一些音频文件.我想为此文件提供部分内容,以便 HTML 音频标签能够搜索和循环.

我怎样才能做到这一点?我知道 httpServeContent 函数可以做到这一点,但我如何通过自己提供文件来做到这一点?我需要在没有这个的情况下执行此操作,以便我可以使用相同的处理程序提供来自不同来源的文件.

解决方案

提供部分内容并非易事.有关介绍,请参阅维基百科上的字节服务.您必须处理特定的状态代码和标头(请求和响应),这并不难,但您不应该自己浪费时间.

如果要提供(或提供)的内容是文件,您可以使用 http.ServeFile() 正如你提到的,它处理服务部分内容(范围请求).

如果要提供的内容不是文件形式,则 http.ServeContent() 是你的朋友:

func ServeContent(w ResponseWriter, req *Request,名称字符串,修改时间时间.时间,内容 io.ReadSeeker)

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

<块引用>

ServeContent 相对于 io.Copy 的主要优点是它可以正确处理 Range 请求、设置 MIME 类型并处理 If-Modified-Since 请求.

您需要做的就是提供一个 io.ReadSeeker查看"您的内容,这是必需的,以便实现可以跳转"到客户端请求的部分,即需要提供服务的部分.你可能会问:怎么做?

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

例如,如果您将内容作为 []byte,您可以获得一个 io.ReadSeeker,如下所示:

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

如果您没有 []byte 的全部内容怎么办?一种选择是提供您自己类型的值来实现 io.ReadSeeker.

io.ReadSeeker 是:

type ReadSeeker interface {读者搜索者}

io.Reader 包含一种方法:

Read(p []byte) (n int, err 错误)

io.Seeker 还包含一种方法:

Seek(offset int64, wherece 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天全站免登陆