使用Go快速创建简单文件上传下载服务

项目文件结构

  • Go版本
    • 1.17.5
  • 项目目录
    • main.go
    • index.html

项目代码

不依赖任何第三方包

main.go

package main

import (
	_ "embed"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
)

//embed是在Go 1.16中新加包。它通过//go:embed指令,可以在编译阶段将静态资源文件打包进编译好的程序中,并提供访问这些文件的能力。
//go:embed index.html
var indexHtml []byte

/**测试页面*/
func index(w http.ResponseWriter, r *http.Request) {
	w.Write(indexHtml)
}

/**上传文件*/
func upload(w http.ResponseWriter, r *http.Request) {
	// 仅允许POST
	if http.MethodPost != r.Method {
		w.WriteHeader(http.StatusMethodNotAllowed)
		w.Write([]byte("Method not allowed"))
		return
	}
	// 获取上传的文件
	file, header, err := r.FormFile("file")
	if nil != err {
		io.WriteString(w, "Read file error: "+err.Error())
		return
	}
	defer file.Close()
	// 创建磁盘文件
	dirFile, err := os.Create(r.FormValue("path") + "/" + header.Filename)
	if nil != err {
		fmt.Fprintf(w, "Create file error: %s", err.Error())
		return
	}
	defer dirFile.Close()
	// 将上传的文件写入磁盘文件
	_, err = io.Copy(dirFile, file)
	if nil != err {
		fmt.Fprintf(w, "Write file error: %s", err.Error())
		return
	}
	fmt.Fprintf(w, "Upload file success, path: %s", dirFile.Name())
}

/**下载文件*/
func download(w http.ResponseWriter, r *http.Request) {
	//获取query参数中的path
	path := r.URL.Query().Get("path")
	if len(path) <= 0 {
		w.WriteHeader(http.StatusBadRequest)
		io.WriteString(w, "Bad request! Download file error, path is required")
		return
	}
	// 打开文件
	file, err := os.Open(path)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		str := "Bad request! Download file error, path is not a file, path:" + path
		io.WriteString(w, str)
		return
	}
	defer file.Close()
	// 从绝对路径中分割出文件名称
	_, filename := filepath.Split(path)
	w.Header().Add("Content-Type", "application/octet-stream")
	w.Header().Add("Content-Disposition", fmt.Sprint("attachment;filename=\"", filename, "\""))
	// 将磁盘文件复制到HTTP输出流
	_, err = io.Copy(w, file)
	if nil != err {
		w.WriteHeader(http.StatusBadRequest)
		_, _ = io.WriteString(w, "Bad request")
	}
}

/**删除文件*/
func delete(w http.ResponseWriter, r *http.Request) {
	path := r.URL.Query().Get("path")
	if len(path) <= 0 {
		w.WriteHeader(http.StatusBadRequest)
		_, _ = io.WriteString(w, "Bad request! Path is required.")
		return
	}
	// 从磁盘中删除文件
	err := os.Remove(path)
	if err != nil {
		str := "Delete file error: " + err.Error()
		io.WriteString(w, str)
		return
	}
	fmt.Fprintf(w, "Delete file success! path: "+path)
}

func main() {
	http.HandleFunc("/", index)
	http.HandleFunc("/upload", upload)
	http.HandleFunc("/download", download)
	http.HandleFunc("/delete", delete)
	// 启动服务监听
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		fmt.Println("ListenAndServe: " + err.Error())
	}
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test</title>
    <script>
        function appendUl(str){
            var el = document.createElement("li");
            el.innerText = str;
            document.getElementById("strUl").append(el);
        }
        function upload(){
            const file = document.getElementById("file");
            const path = document.getElementById("path");
            const form = new FormData();
            form.append("file",file.files[0]);
            form.append("path",path.value);
            fetch("/upload",{
                method:"POST",body:form,
            }).then(r=>r.ok&&r.text())
                .then(s=>appendUl("文件上传:"+s));
        }
        function downloadPath(e){
            const path = e.value;
            const dom = document.getElementById("download");
            dom.href = encodeURI("/download?path="+path);
            dom.innerText = "下载"+path;
        }
        function deleteFile(){
            fetch(encodeURI("/delete?path="+document.getElementById("path2").value))
                .then(r=>r.ok&&r.text()).then(s=>appendUl("文件删除:"+s));
        }
    </script>
</head>
<body>
<h1>Test page</h1>
<br>上传路径:<input type="text" name="path" id="path">
<br>文件:<input type="file" name="file" id="file">
<br><button onclick="upload()">上传文件</button>
<br>下载及删除路径:<input type="text" name="path2" id="path2" onchange="downloadPath(this)">
<br><button onclick="deleteFile()">删除文件</button>
<br><a href="" id="download" target="_blank">下载文件</a>
<br><ul id="strUl"></ul>
</body>
</html>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章