Golang 實現文件上傳和下載服務
前言
在開發的過程中,難免會碰到上傳 / 下載文件的場景。如果這個功能服務端沒開發好,就沒法進行測試。
所以每次都要自己先實現一遍,本文使用 go
寫了一個簡單的文件上傳和下載服務。
以後再碰到這種場景的時候就可以快速進行開發。
下載
因爲下載比較簡單, go
語言默認就有,所以先來說一下下載。
熟悉 go
的都知道, go
對文件服務器有默認的支持,所以我們直接調用相關的 API
就能完成對應的操作。
http.Handle("/", http.FileServer(http.Dir("/tmp/Downloads")))
http.ListenAndServe(":8080", nil)
在這裏需要用 http
包中的 FileServer
函數,它需要一個文件夾,我這裏使用的是一個臨時目錄 /tmp/Downloads
。
接着需要把這個 Handler
綁定到一個路由中,這裏綁定的就是 /
。
最後需要啓動這個服務,我把這個服務綁定到 8080
端口,然後使用 go run main.go
就可以運行服務器了。
你可以通過 http://localhost:8080/
來查看 /tmp/Downloads
下所有的文件。
上傳
與下載不同的是, go
沒有提供默認的實現(也許有,我不知道),所以我們需要自己實現。
實現文件上傳也比較簡單
func uploadHandler(w http.ResponseWriter, r *http.Request) {
fmt.Println("Receive Upload: ", time.Now())
file, header, err := r.FormFile("file")
if err != nil {
fmt.Println("Failed to get file data ", err.Error())
_, _ = io.WriteString(w, err.Error())
return
}
defer file.Close()
newFile, err := os.Create(header.Filename)
if err != nil {
fmt.Println("Failed to create file ", err.Error())
return
}
defer newFile.Close()
_, err = io.Copy(newFile, file)
if err != nil {
fmt.Println("Copy ", header.Filename, " to ", newFile.Name(), "failed ", err.Error())
return
}
fmt.Println("Upload File Success ", newFile.Name(), ",", time.Now())
}
func main() {
http.HandleFunc("/upload", uploadHandler)
http.ListenAndServe(":8080", nil)
}
我們把上傳的邏輯放到 uploadHandler
這個函數中,並綁定到 /upload
這個路由上。
在 uploadHandler
中會從表單中讀取 file
的文件,然後用它在本地創建一個同名的文件,接着把內容拷貝到新創建的本地文件中。這樣就完成了。
現在我們就可以使用 curl
來測試一下上傳文件
curl -X POST http://localhost:8080/upload \
-F "file=@/tmp/upload.go" \
-H "Content-Type: multipart/form-data"
不出所料,執行完成之後,在當前文件夾下多出了 upload.go
這個文件。
完整代碼
package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func uploadHandler(w http.ResponseWriter, r *http.Request) {
fmt.Println("Receive Upload: ", time.Now())
file, header, err := r.FormFile("file")
if err != nil {
fmt.Println("Failed to get file data ", err.Error())
_, _ = io.WriteString(w, err.Error())
return
}
defer file.Close()
newFile, err := os.Create(header.Filename)
if err != nil {
fmt.Println("Failed to create file ", err.Error())
return
}
defer newFile.Close()
_, err = io.Copy(newFile, file)
if err != nil {
fmt.Println("copy ", header.Filename, " to ", newFile.Name(), "failed ", err.Error())
return
}
fmt.Println("Upload File Success ", newFile.Name(), ",", time.Now())
}
func main() {
fmt.Println("Start Go Download Upload Server...")
http.HandleFunc("/upload", uploadHandler)
http.Handle("/", http.FileServer(http.Dir("/tmp/Downloads")))
http.ListenAndServe(":8080", nil)
}
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/G-lHXl1QIWv7Yvk2Bd1uqg