如何使用 Go 提供 http 部分内容?

Posted

技术标签:

【中文标题】如何使用 Go 提供 http 部分内容?【英文标题】:How to serve http partial content with Go? 【发布时间】:2016-08-01 03:18:39 【问题描述】:

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

我怎样才能做到这一点?我知道httpServeContent 功能可以做到这一点,但我如何通过自己提供文件来做到这一点?我需要不这样做,以便我可以使用相同的处理程序提供来自不同来源的文件。

【问题讨论】:

【参考方案1】:

提供部分内容并非易事。有关介绍,请参阅***上的 Byte serving。您必须处理特定的状态代码和标头(请求和响应),这并不难,但您不应该自己浪费时间。

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

如果要提供的内容不是文件,那么http.ServeContent() 就是你的朋友:

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

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

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

您需要做的就是提供内容的io.ReadSeeker“视图”,这是必需的,以便实现可以“跳转”到客户端请求的部分,即需要服务的部分。您可能会问:如何做到这一点?

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

例如,如果您的内容为[]byte,您可能会像这样获得io.ReadSeeker

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

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

io.ReadSeeker 是:

type ReadSeeker interface 
    Reader
    Seeker

io.Reader 包含一种方法:

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

io.Seeker 还包含一种方法:

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

您的内容可以在某个地方访问,不知何故,您知道如何。调用Seek() 是为了让您知道您的内容需要哪个部分(位置),并调用Read() 以便您可以填充传递的切片(以提供实际内容)。请注意,这些方法可能会被多次调用,因此您必须跟踪您在内容(源)中的位置。如果您选择走这条路,请阅读链接接口的文档,以确保您符合接口的“通用合同”以避免意外错误。

【讨论】:

以上是关于如何使用 Go 提供 http 部分内容?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Go 提供动态创建的 URL 路径?

如何使用基本身份验证提供静态文件?

[教程,Part 2]如何使用HTTP/REST端点,中间件,Kubernetes等开发Go gRPC微服务

如果 URL 与 Go 中的任何模式都不匹配,如何提供文件?

如何使用 Go 有效地下载大文件?

如何使用 Http Post 从 WebView 中检索和修改 HTML 内容