在Go的网站地址路径中,将文件系统中的两个文件夹作为一个虚拟文件夹。

huangapple go评论75阅读模式
英文:

Two folders in the file system as one virtual folder in the path of the site address (web server in Go)

问题

我在文件系统中有两个文件夹,分别是"files1"和"files2"。

我可以将文件系统中的一个文件夹作为站点地址路径下的一个虚拟文件夹进行托管,代码如下:

http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir("./files1"))))

如何将"files1"和"files2"文件夹的内容都托管到站点地址路径"/public/"下呢?

英文:

I have two folders in the file system "files1" and "files2".

I can host one folder in the file system as one virtual folder in the path of the site address like this:

http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir("./files1"))))

How can I host the contents of the "files1" and "files2" folders on the same path of the site address "/public/" ?

答案1

得分: 4

一个简单的解决方案是实现http.FileSystem接口。

以下是示例代码:

package main

import (
	"errors"
	"io/fs"
	"net/http"
)

func main() {
	http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(mergedDir{
		Dir1: http.Dir("./files1"),
		Dir2: http.Dir("./files2"),
	})))

	http.ListenAndServe(":8080", nil)
}

type mergedDir struct {
	Dir1 http.Dir // 首先尝试访问Dir1,因此它具有更高的优先级。
	Dir2 http.Dir
}

func (d mergedDir) Open(name string) (http.File, error) {
	f, err := d.Dir1.Open(name)

	if err != nil {
		if errors.Is(err, fs.ErrNotExist) {
			return d.Dir2.Open(name)
		}
	}

	return f, err
}

我已经使用以下目录结构进行了测试:

├── files1
│   ├── f1-1.txt
│   └── f1-sub
│       └── f1-s.txt
└── files2
    ├── f1-1.txt
    ├── f2-1.txt
    └── f2-sub
        └── f2-s.txt

有两个f1-1.txt,因为首先尝试访问files1,所以会提供files1中的版本。


更新

根据作者的要求,这是支持多个目录的mergedDir的另一个版本:

type mergedDir struct {
	Dirs []http.Dir
}

func (d mergedDir) Open(name string) (http.File, error) {
	for _, dir := range d.Dirs {
		f, err := dir.Open(name)
		if err == nil {
			return f, nil
		}
		if !errors.Is(err, fs.ErrNotExist) {
			return f, err
		}
	}

	return nil, fs.ErrNotExist
}
英文:

A simple solution is to implement the http.FileSystem interface.

Here is the demo:

package main

import (
	"errors"
	"io/fs"
	"net/http"
)

func main() {
	http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(mergedDir{
		Dir1: "./files1",
		Dir2: "./files2",
	})))

	http.ListenAndServe(":8080", nil)
}

type mergedDir struct {
	Dir1 http.Dir // Dir1 will be tried first so it has higher priority.
	Dir2 http.Dir
}

func (d mergedDir) Open(name string) (http.File, error) {
	f, err := d.Dir1.Open(name)

	if err != nil {
		if errors.Is(err, fs.ErrNotExist) {
			return d.Dir2.Open(name)
		}
	}

	return f, err
}

I have tested with this directory structure:

├── files1
│   ├── f1-1.txt
│   └── f1-sub
│       └── f1-s.txt
└── files2
    ├── f1-1.txt
    ├── f2-1.txt
    └── f2-sub
        └── f2-s.txt

There are two f1-1.txt, the one in files1 is served because files1 is tried first.


Update:

Another version of mergedDir to support multiple directories as requested by the author:

type mergedDir struct {
	Dirs []http.Dir
}

func (d mergedDir) Open(name string) (http.File, error) {
	for _, dir := range d.Dirs {
		f, err := dir.Open(name)
		if err == nil {
			return f, nil
		}
		if !errors.Is(err, fs.ErrNotExist) {
			return f, err
		}
	}

	return nil, fs.ErrNotExist
}

huangapple
  • 本文由 发表于 2023年4月5日 21:26:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/75940008.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定