进阶 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 表单,如下所示:htmlUpload 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
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
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