进阶 www.iris-go.com 2026-10-20 02:39:14 · 19 阅读

第8章 Party.HandleDir 静态文件服务与 DirOptions 配置详解

第8章 引言 从指定目录(系统物理目录或嵌入应用程序的目录)提供静态文件是由 Party.HandleDir 方法完成的。HandleDir 注册一个处理器,用于通过文件系统(物理或嵌入)的内容来提供 HTTP 请求。 第一个参数:路由路径 第二个参数:需要提供的文件系统 第三个参数:可选的目录选项 ```go HandleDir(requestPath string, fs http.FileSystem, opts ...DirOptions) []*Route ``` DirOptions 结构体如下所示: ```go type DirOptions struct { // 默认值为 "/index.html",如果请求路径以 / 结尾且 $IndexName // 未被设置,则重定向到该路径。 // 该 index 处理器由框架自动注册,但可以被覆盖。 IndexName string // PushTargets 将文件名(map 的 value)推送给客户端, // 以便在请求特定路径(map 的 key 不含前缀)且该路径不是目录(即是一个 `IndexFile`)时, // 无需客户端额外请求即可提供这些文件(HTTP/2 Push)。 // // 示例: // "/": { // "favicon.ico", // "js/main.js", // "css/main.css", // } PushTargets map[string][]string // PushTargetsRegexp 类似于 `PushTargets`,但接受正则在目录下的所有文件(递归)上进行匹配。 // 应设置 `IndexName`。 // // 示例: // "/": regexp.MustCompile("((.*).js|(.*).css|(.*).ico)$") // 同时参见 `iris.MatchCommonAssets`。 PushTargetsRegexp map[string]*regexp.Regexp // Cache 用于启用内存缓存并预压缩文件。 Cache DirCacheOptions // 指定文件应在何种情况下以压缩形式提供。 Compress bool // 如果未找到 `IndexName`,则列出当前请求目录内的文件。 ShowList bool // 如果 `ShowList` 为 true,则使用此函数替代默认函数来展示当前请求目录中的文件列表。 // 同时参见 `DirListRich` 包级函数。 DirList DirListFunc // 本地下载并保存的文件。 Attachments Attachments // 可选的校验器,遍历每个请求的资源。 AssetValidator func(ctx *context.Context, name string) bool } ``` 快速上手 假设你的可执行文件旁边有一个 `./assets` 文件夹,并希望这些文件通过 `http://localhost:8080/static//*` 路由提供。代码如下: ```go app := iris.New() app.HandleDir("/static", iris.Dir("./assets")) app.Listen(":8080") ``` 如果你希望将静态文件嵌入到可执行文件的构建产物中,从而避免依赖系统目录,可以使用 `go-bindata` 这样的工具将文件转换为程序内的 `[]byte`。下面是一个快速教程,介绍如何使用 Iris 来服务这些数据。 安装 `go-bindata`: ```bash $ go get -u github.com/go-bindata/go-bindata/v3/go-bindata ``` 导航到包含 `./assets` 子目录的程序目录,并执行: ```bash $ go-bindata -fs -prefix "assets" ./assets/... ``` 上述命令会生成一个包含 `AssetFile()` 函数的 Go 文件,该函数返回一个兼容的 `http.FileSystem`,你可以将其提供给 Iris 以提供文件服务。 ```go app := iris.New() app.HandleDir("/static", AssetFile()) ``` 运行你的应用: ```bash $ go run . ``` `HandleDir` 支持所有标准功能,包括 `content-range`,无论是物理目录、嵌入式目录还是缓存目录。 但是,如果你只需要一个处理器来工作,而不需要注册路由,可以使用 `iris.FileServer` 的包级函数。 `FileServer` 函数返回一个 `Handler`,它从指定的系统目录、嵌入式目录或内存缓存目录中提供文件。 ```go iris.FileServer(fs http.FileSystem, options DirOptions) ``` 用法示例: ```go handler := iris.FileServer(iris.Dir("./assets"), iris.DirOptions { ShowList: true, Compress: true, IndexName: "index.html", }) ``` 示例 ​ 我们来创建一个应用:用户可以上传一个或多个文件,并列出这些文件。复制粘贴 main.go 的内容: ```go package main import ( "crypto/md5" "fmt" "io" "mime/multipart" "os" "strconv" "strings" "time" "github.com/kataras/iris/v12" ) func init() { os.Mkdir("./uploads", 0700) } func main() { app := iris.New() app.RegisterView(iris.HTML("./views", ".html")) // 提供静态资源(如 javascript、css)。 app.HandleDir("/public", iris.Dir("./public")) app.Get("/", index) app.Get("/upload", uploadView) app.Post("/upload", upload) app.HandleDir("/files", iris.Dir("./uploads"), iris.DirOptions{ Compress: true, ShowList: true, }) app.Listen(":8080") } func index(ctx iris.Context) { ctx.Redirect("/upload") } func uploadView(ctx iris.Context) { now := time.Now().Unix() h := md5.New() io.WriteString(h, strconv.FormatInt(now, 10)) token := fmt.Sprintf("%x", h.Sum(nil)) ctx.View("upload.html", token) } const maxSize = 10 * iris.MB func upload(ctx iris.Context) { ctx.SetMaxRequestBodySize(maxSize) _, _, err := ctx.UploadFormFiles("./uploads", beforeSave) if err != nil { ctx.StopWithError(iris.StatusPayloadTooRage, err) return } ctx.Redirect("/files") } func beforeSave(ctx iris.Context, file *multipart.FileHeader) { ip := ctx.RemoteAddr() ip = strings.ReplaceAll(ip, ".", "_") ip = strings.ReplaceAll(ip, ":", "_") file.Filename = ip + "-" + file.Filename } ``` 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
./views/upload.html 是一个简单的 HTML 表单,如下所示:html Upload Files
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

评论 (0)