gpt4 book ai didi

http - Golang 从内存中提供静态文件

转载 作者:IT老高 更新时间:2023-10-28 13:04:07 33 4
gpt4 key购买 nike

我有一个关于在 Go 中提供文件的快速问题。有一个非常省时的 FileServer 处理程序,但对于我的用例,我的应用程序只有 2 或 3 个文件(js 和 css),我不想让部署复杂化而不得不考虑这些。

您是否认为有一种简单的方法可以将这两个文件构建到二进制文件中并从那里提供它们。例如,base64 将文件的数据编码为常量,并从常量中服务文件。这将以最简单的形式工作,但我不想独自完成文件服务器所做的一切(标题、到期、mime 类型等)的痛苦。那么是否有一种简单的方法可以将这些静态文件以某种形式烘焙到二进制文件中并以这种方式提供服务?

最佳答案

FileServer 在其构造函数中需要一个FileSystem 对象。通常,您会提供基于 http.Dir 的内容,以便从实际的文件系统为您制作 FileSystem,但没有什么能阻止您实现自己的:

package main

import "os"
import "time"
import "net/http"

type InMemoryFS map[string]http.File

// Implements FileSystem interface
func (fs InMemoryFS) Open(name string) (http.File, error) {
if f, ok := fs[name]; ok {
return f, nil
}
panic("No file")
}

type InMemoryFile struct {
at int64
Name string
data []byte
fs InMemoryFS
}

func LoadFile(name string, val string, fs InMemoryFS) *InMemoryFile {
return &InMemoryFile{at: 0,
Name: name,
data: []byte(val),
fs: fs}
}

// Implements the http.File interface
func (f *InMemoryFile) Close() error {
return nil
}
func (f *InMemoryFile) Stat() (os.FileInfo, error) {
return &InMemoryFileInfo{f}, nil
}
func (f *InMemoryFile) Readdir(count int) ([]os.FileInfo, error) {
res := make([]os.FileInfo, len(f.fs))
i := 0
for _, file := range f.fs {
res[i], _ = file.Stat()
i++
}
return res, nil
}
func (f *InMemoryFile) Read(b []byte) (int, error) {
i := 0
for f.at < int64(len(f.data)) && i < len(b) {
b[i] = f.data[f.at]
i++
f.at++
}
return i, nil
}
func (f *InMemoryFile) Seek(offset int64, whence int) (int64, error) {
switch whence {
case 0:
f.at = offset
case 1:
f.at += offset
case 2:
f.at = int64(len(f.data)) + offset
}
return f.at, nil
}

type InMemoryFileInfo struct {
file *InMemoryFile
}

// Implements os.FileInfo
func (s *InMemoryFileInfo) Name() string { return s.file.Name }
func (s *InMemoryFileInfo) Size() int64 { return int64(len(s.file.data)) }
func (s *InMemoryFileInfo) Mode() os.FileMode { return os.ModeTemporary }
func (s *InMemoryFileInfo) ModTime() time.Time { return time.Time{} }
func (s *InMemoryFileInfo) IsDir() bool { return false }
func (s *InMemoryFileInfo) Sys() interface{} { return nil }

const HTML = `<html>
Hello world !
</html>
`

const CSS = `
p {
color:red;
text-align:center;
}
`

func main() {
FS := make(InMemoryFS)
FS["foo.html"] = LoadFile("foo.html", HTML, FS)
FS["bar.css"] = LoadFile("bar.css", CSS, FS)
http.Handle("/", http.FileServer(FS))
http.ListenAndServe(":8080", nil)
}

这个实现充其量是非常错误,你可能永远不应该使用它,但它应该告诉你FileSystem接口(interface)可以如何实现任意'文件'。

可以使用更可靠(当然危险性更低)的类似实现 here .这个是用来fake the filesystem的在 Go Playground 上,所以它应该是一个很好的引用(反正比我的要好得多)。

是否像其他建议的那样重新实现此 FileSystem 接口(interface)或自定义 FileServer 是否更简单,完全取决于您和您的项目!然而,我怀疑对于几个预定义文件的服务,重写服务部分可能比模拟完整的文件系统更容易。

关于http - Golang 从内存中提供静态文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21595295/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com