打印

golang的一个文件服务器

[复制链接]
748|6
跳转到指定楼层
楼主
可以显示指定目录,进入子目录,下载文件,上传文件等等

@sherwin @海中水 @gaoyang9992006

  1. go run fileserver.go -p=1234
复制代码



显示指定目录:





进入子目录:



上传文件:





fileserver.go
代码如下:


  1. package main

  2. import (
  3.         "flag"
  4.         "fmt"
  5.         "io"
  6.         "io/ioutil"
  7.         "log"
  8.         "net/http"
  9.         "os"
  10.         "path"
  11.         "strconv"
  12.         "strings"
  13.         "time"
  14. )

  15. var defaultPath string

  16. var baseURL string
  17. var upload_path string

  18. func Logger(req *http.Request, statusCode int) {
  19.         const layout = "[ 2/Jan/2006 15:04:05 ]"
  20.         fmt.Println(baseURL + " --- " + time.Now().Format(layout) + " " + req.Method + "  " + strconv.Itoa(statusCode) + "  " + req.URL.Path)
  21. }

  22. func Handler(w http.ResponseWriter, req *http.Request) {


  23.         filename := defaultPath + req.URL.Path[1:]
  24.         fmt.Println("=+=== file name: ",filename)
  25.         if last := len(filename) - 1; last >= 0 && filename[last] == '/' && len(filename) != 1 {
  26.                 filename = filename[:last]
  27.         }

  28.         if req.Method == "POST" {
  29.                 file, head, err := req.FormFile("file")
  30.                 if err != nil {
  31.                         fmt.Println(err)
  32.                         return
  33.                 }

  34.                 defer file.Close()


  35.                 //创建文件
  36.                 fW, err := os.Create(upload_path + head.Filename)
  37.                 if err != nil {
  38.                         fmt.Println("文件创建失败")
  39.                         return
  40.                 }
  41.                 defer fW.Close()

  42.                 _, err = io.Copy(fW, file)
  43.                 if err != nil {
  44.                         fmt.Println("文件保存失败")
  45.                         return
  46.                 }
  47.         }

  48.         // Empty request (Root)
  49.         if filename == "" {
  50.                 filename = "./"
  51.         }

  52.         file, err := os.Stat(filename)

  53.         // 404 if file doesn't exist
  54.         if os.IsNotExist(err) {
  55.                 _, err = io.WriteString(w, "404 Not Found")
  56.                 Logger(req, http.StatusNotFound)
  57.                 return
  58.         }

  59.         // Serve directory
  60.         if file.IsDir() {

  61.                 slashCheck := ""

  62.                 files, err := ioutil.ReadDir(filename)
  63.                 // Catch the Error in reading from directory
  64.                 if err != nil {
  65.                         http.Redirect(w, req, "", http.StatusInternalServerError)
  66.                         Logger(req, http.StatusInternalServerError)
  67.                 }
  68.                 // Checking for Root Directory
  69.                 if filename != "./" {
  70.                         if filename[len(filename)-1] != '/' {
  71.                                 slashCheck = "/"
  72.                         }
  73.                 }

  74.                 fmt.Println("=+=== slashCheck: ",slashCheck)
  75.                 fmt.Println("=+=== req.URL.Path[0:]: ",req.URL.Path[0:])

  76.                 responseString := "<html><body> <h3> Directory Listing for " + req.URL.Path[1:] + "/ </h3> <br/> <hr> <ul>"
  77.                 for _, f := range files {
  78.                         if f.Name()[0] != '.' {
  79.                                 if f.IsDir() {
  80.                                         responseString += "<li><a href=\"" + req.URL.Path[0:] + slashCheck + f.Name() + "\">" + f.Name() + "/" + "</a></li>"
  81.                                 } else {
  82.                                         responseString += "<li><a href=\"" + req.URL.Path[0:] + slashCheck + f.Name() + "\">" + f.Name() + "</a></li>"
  83.                                 }
  84.                         }
  85.                 }

  86.                 //Ending the list
  87.                 responseString += "</ul><br/><hr/>"

  88.                 p := req.URL.Path

  89.                 // Display link to parent directory
  90.                 if len(p) > 1 {
  91.                         base := path.Base(p)

  92.                         slice := len(p) - len(base) - 1

  93.                         url := "/"

  94.                         if slice > 1 {
  95.                                 url = req.URL.Path[:slice]
  96.                                 url = strings.TrimRight(url, "/") // Remove extra / at the end
  97.                         }

  98.                         responseString += "<br/><a href=\"" + url + "\">Parent directory</a>"
  99.                 }

  100.                 uploadStr := "<form action='#' method=\"post\" enctype=\"multipart/form-data\"> <label> </label><input type=\"file\" name='file'  /><br/><br/> <label><input type=\"submit\" value=\"上传文件\"/></label> </form>"

  101.                 responseString = responseString + uploadStr + "</body></html>"
  102.                 //fmt.Println("      =+=== responseString: ",responseString)
  103.                 _, err = io.WriteString(w, responseString)
  104.                 if err != nil {
  105.                         // panic(err)
  106.                         http.Redirect(w, req, "", http.StatusInternalServerError)
  107.                         Logger(req, http.StatusInternalServerError)
  108.                 } else {
  109.                         Logger(req, http.StatusOK)
  110.                 }

  111.                 upload_path = "./" + req.URL.Path[0:] + "/"

  112.                 return
  113.         }

  114.         // File exists and is no directory; Serve the file

  115.         b, err := ioutil.ReadFile(filename)
  116.         if err != nil {
  117.                 http.Redirect(w, req, "", http.StatusInternalServerError)
  118.                 Logger(req, http.StatusInternalServerError)
  119.                 return
  120.         }

  121.         str := string(b)
  122.         extension := path.Ext(filename)

  123.         if extension == ".css" {
  124.                 w.Header().Set("Content-Type", "text/css; charset=utf-8")
  125.         } else if extension == ".js" {
  126.                 w.Header().Set("Content-Type", "application/javascript; charset=utf-8")
  127.         }
  128.         _, err = io.WriteString(w, str)
  129.         if err != nil {
  130.                 // panic(err)
  131.                 http.Redirect(w, req, "", http.StatusInternalServerError)
  132.         } else {
  133.                 Logger(req, http.StatusOK)
  134.         }

  135. }

  136. func main() {

  137.         defaultPortPtr := flag.String("p", "", "Port Number")
  138.         defaultPathPtr := flag.String("d", "", "Root Directory")
  139.         flag.Parse()

  140.         portNum := "8080"

  141.         // Handling the command line flags

  142.         // Directory
  143.         if *defaultPathPtr != "" {
  144.                 defaultPath = "./" + *defaultPathPtr + "/"
  145.         } else {
  146.                 defaultPath = ""
  147.         }
  148.         // Port Number
  149.         if *defaultPortPtr != "" {
  150.                 portNum = *defaultPortPtr
  151.         } else {
  152.                 portNum = "8080"
  153.         }

  154.         baseURL = "http://localhost:" + portNum

  155.         fmt.Println("Serving on ", baseURL, " subdirectory ", defaultPath)

  156.         http.HandleFunc("/", Handler)
  157.         err := http.ListenAndServe(":"+portNum, nil)
  158.         if err != nil {
  159.                 log.Fatal("ListenAndServe: ", err)
  160.         }
  161. }
复制代码


沙发
| 2019-9-20 09:14 | 只看该作者
不错的东西。给你点个赞。
板凳
 楼主 | 2019-9-20 09:26 | 只看该作者
海中水 发表于 2019-9-20 09:14
不错的东西。给你点个赞。

可以交叉编译到嵌入式linux环境里:
env GOOS=linux GOARCH=arm go build -v fileserver.go

这样可以很方便为嵌入式环境增加远程查看,更新,下载功能
地板
| 2019-9-20 10:29 | 只看该作者
相当于一个NAS么?
5
 楼主 | 2019-9-20 13:23 | 只看该作者
sherwin 发表于 2019-9-20 10:29
相当于一个NAS么?

可以的
6
| 2019-9-23 09:18 | 只看该作者
keer_zu 发表于 2019-9-20 09:26
可以交叉编译到嵌入式linux环境里:
env GOOS=linux GOARCH=arm go build -v fileserver.go

ok!有空研究一下。
7
| 2019-9-23 16:27 | 只看该作者
为啥不用gin....可以少些不少代码...
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

关闭

热门推荐上一条 /6 下一条

在线客服 快速回复 返回顶部 返回列表
猎豹彩票 爱投彩票 22彩票 916彩票app 22彩票 山东群英会选号技巧 河北11选5 快赢彩票计划 22彩票 华阳彩票