項目文件結構
- 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>