Golang HTTP Fileserver

概要

fileserver是静态文件服务,其主要功能是根据提供文件查询与文件传输的功能。由golang标准库提供。

入口函数

func FileServer(root FileSystem) Handler {
	return &fileHandler{root}
}

type fileHandler struct {
	root FileSystem
}

它的入参是一个带有根路径的文件系统,返回值是一个http_handler(处理函数)

FileSystem文件系统,支持访问文件路径,无论使用何种操作系统,文件路径通过‘/’进行分隔

type FileSystem interface {
	Open(name string) (File, error) // 打开一个文件
}

type File interface {
	io.Closer // 关闭文件
	io.Reader // 读文件
	io.Seeker // 文件位置信息
	Readdir(count int) ([]os.FileInfo, error) // 读文件夹
	Stat() (os.FileInfo, error) // 文件状态
}

处理函数

func (f *fileHandler) ServeHTTP(w ResponseWriter, r *Request) {
	upath := r.URL.Path
	if !strings.HasPrefix(upath, "/") { // 改写path
		upath = "/" + upath
		r.URL.Path = upath
	}
	serveFile(w, r, f.root, path.Clean(upath), true) // 核心逻辑
}

func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirect bool) {
        f, err := fs.Open(name) // 打开文件,全路径是由root+name
        d, err := f.Stat()
	if d.IsDir() { // 如果path指向的是文件夹
		if checkIfModifiedSince(r, d.ModTime()) == condFalse { // 判断文件夹是否更新
			writeNotModified(w)
			return
		}
		setLastModified(w, d.ModTime()) // 写入文件夹更新时间
		dirList(w, r, f) // 见后
		return
	}

	// 如果path指向的是文件
	sizeFunc := func() (int64, error) { return d.Size(), nil }
	serveContent(w, r, d.Name(), d.ModTime(), sizeFunc, f) // 这部分代码比较复杂,起主要逻辑是通过request中的range信息,多线程读取文件内容,返回写入response中。从中我们可以看到静态服务器是支持断点续传的http服务
}

文件夹列表

func dirList(w ResponseWriter, r *Request, f File) {
	dirs, err := f.Readdir(-1) // 读文件夹
	sort.Slice(dirs, func(i, j int) bool { return dirs[i].Name() < dirs[j].Name() }) // 按照文件名进行排序
        // 写html格式的response
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	fmt.Fprintf(w, "<pre>\n")
	for _, d := range dirs {
		name := d.Name()
		if d.IsDir() { // 如果是子目录
			name += "/"
		}
		url := url.URL{Path: name}
		fmt.Fprintf(w, "<a href=\"%s\">%s</a>\n", url.String(), htmlReplacer.Replace(name))
	}
	fmt.Fprintf(w, "</pre>\n")
}

用于将字符串路径转换为文件系统

主要的功能是兼容不同的os

定义

type Dir string
// name是当前os的文件路径格式
func (d Dir) Open(name string) (File, error) {
	dir := string(d) // 根目录
	if dir == "" {
		dir = "."
	}
	fullName := filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name))) // 拼出全路径
	f, err := os.Open(fullName)
	if err != nil {
		return nil, mapDirOpenError(err, fullName)
	}
	return f, nil
}

辅助中间件

// 该函数对象改写request的path,是一个中间件
func StripPrefix(prefix string, h Handler) Handler {
	if prefix == "" {
		return h
	}
	return HandlerFunc(func(w ResponseWriter, r *Request) { // 其定义见后
		if p := strings.TrimPrefix(r.URL.Path, prefix); len(p) < len(r.URL.Path) { // 前缀匹配
			r2 := new(Request) // 创建一个新的request
			*r2 = *r
			r2.URL = new(url.URL)
			*r2.URL = *r.URL
			r2.URL.Path = p // 改写path
			h.ServeHTTP(w, r2) // 调用hander的处理逻辑
		} else {
			NotFound(w, r)
		}
	})
}

type HandlerFunc func(ResponseWriter, *Request) // 定义一个函数对象

func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { // 该函数对象的ServeHTTP方法是执行自身
	f(w, r)
}

put it together

http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static"))))


 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
gohttp是一个http的文件服务器,因为是用go语言写的,所以加了一个go的抬头。之所以用go是因为发布起来是一个二进制文件,不同的平台都可以用,而且没有依赖问题,且稳定性也很好。    这个软件从很久以前就开始写了,第一次提交实在2015年的2月11号,作为组内存放公共文件的一个小软件。一开始的功能只有像 python -mSimpleHTTPServer 那种简单的功能。但是当我看到gotty这个软件的时候 ,意思到一个简单的软件竟然可以做到如此出色。之后这个http文件服务器就不断的被优化着,保持着简单易用的同时,开始赋予了它最强大的功能。    这个软件有很多的技术,隐藏在了其简易朴实的外表之下。请容我简单的介绍下pjax简称页面ajax技术        在gohttp进行目录却换的时候,你会看到地址栏在变,但是页面却是局部刷新的。各种文件的预览功能        所有常见的代码都可以直接在gohttp下预览,如果你用的是chrome浏览器的话,包括pdf,mp4,mp3都可以直接预览。实时的目录zip打包下载        强大的体现在它是实时的,即使你马上在目录下新增了一个文件,点击目录zip下载的时候,这个文件也会出现在里面。二维码的支持        手机下载往往没有电脑下载这么容易,点点鼠标就可以了。但是有了二维码,手机也只用扫一扫就可以下载了。苹果应用的在线安装        iphone应用安装包的扩展名是ipa,但是你还必须有个额外的plist文件才行。以及生成一个itms-services开头的地址,gohttp直接把这些工作都做了,ipa的解析,plist以及下载页面的自动生成。同普通文件一样,只需要点击右侧的生成二维码,然后用iphone手机扫描下,iphone的应用就安装到了你的手机上。PS:坑爹的苹果,就不能像安卓一样简单一点吗README文件的自动显示像github网站上的项目,readme文件都会作为项目的介绍自动显示出来。gohttp也借鉴了一下。如果目录下有readme文件的话,就会自动预览出来。文件上传简单的文件上传也有着出色的表现,可以看到上传的进度,以及支持拖拽的方式上传文件。为了更方便的结合自动发布的功能,文件上传也有其相应的API,上传的时候也可是指定软件的版本号,存储结构参考了python,pypi官方的模式。还有很多很多其他的特性    http basic auth认证,不同文件不同的icon,gzip支持,目录的整合显示.... 还有很多功能等待着你去发现和有能力的你去补充。    截图  标签:gohttp

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值