使用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>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章