背景
簡(jiǎn)單需要一個(gè)文件服務(wù)器來傳遞數(shù)據(jù),只要兩個(gè)功能,一個(gè)上傳接口,一個(gè)下載接口。
選用go http模塊實(shí)現(xiàn),比nginx、ftp等更方便快捷。
需求整理
- 上傳接口"/v1/file_upload/"
- 上傳接口增加簡(jiǎn)單BasicAuth鑒權(quán)
- 上傳成功返回下載URL
json格式返回
電梯直達(dá)
只想文件上傳服務(wù)器測(cè)試接口,以下電梯直達(dá)即可
CSDN 5積分下載
白嫖
測(cè)試效果
GO代碼實(shí)現(xiàn)
package main
import (
"bytes"
"encoding/base64"
"encoding/json"
"flag"
"fmt"
"io"
"log"
"net/http"
"os"
"path/filepath"
"strings"
)
type ViewFunc func(http.ResponseWriter, *http.Request)
func http_resp(code int, msg string, w http.ResponseWriter) {
var Result map[string]interface{}
Result = make(map[string]interface{})
Result["code"] = code
Result["msg"] = msg
data, err := json.Marshal(Result)
if err != nil {
log.Printf("%v\n", err)
}
w.Write([]byte(string(data)))
}
func upload(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
t, _ := template.ParseFiles("upload.html")
t.Execute(w, nil)
return
}
contentType := r.Header.Get("content-type")
contentLen := r.ContentLength
if !strings.Contains(contentType, "multipart/form-data") {
http_resp(-1001, "The content-type must be multipart/form-data", w)
return
}
//限制最大文件大小
if contentLen >= 50*1024*1024 {
http_resp(-1002, "Failed to large,limit 50MB", w)
return
}
err := r.ParseMultipartForm(50 * 1024 * 1024)
if err != nil {
http_resp(-1003, "Failed to ParseMultipartForm", w)
return
}
if len(r.MultipartForm.File) == 0 {
http_resp(-1004, "File is NULL", w)
return
}
var Result map[string]interface{}
Result = make(map[string]interface{})
Result["code"] = 0
DownLoadUrl := "http://192.168.10.9:8080/"
FileCount := 0
for _, headers := range r.MultipartForm.File {
for _, header := range headers {
log.Printf("recv file: %s\n", header.Filename)
filePath := filepath.Join("./upload", header.Filename)
dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
log.Printf("Create file %s error: %s\n", filePath, err)
return
}
srcFile, err := header.Open()
if err != nil {
log.Printf("Open header failed: %s\n", err)
}
_, err = io.Copy(dstFile, srcFile)
if err != nil {
log.Printf("Write file %s error: %s\n", filePath, err)
}
_, _ = srcFile.Close(), dstFile.Close()
FileCount++
name := fmt.Sprintf("file%d_url", FileCount)
Result[name] = (DownLoadUrl + header.Filename)
}
}
data, err := json.Marshal(Result)
if err != nil {
log.Printf("%v \n", err)
}
w.Write([]byte(string(data)))
}
func BasicAuth(f ViewFunc, user, passwd []byte) ViewFunc {
return func(w http.ResponseWriter, r *http.Request) {
basicAuthPrefix := "Basic "
// 獲取 request header
auth := r.Header.Get("Authorization")
// 如果是 http basic auth
if strings.HasPrefix(auth, basicAuthPrefix) {
// 解碼認(rèn)證信息
payload, err := base64.StdEncoding.DecodeString(
auth[len(basicAuthPrefix):],
)
if err == nil {
pair := bytes.SplitN(payload, []byte(":"), 2)
if len(pair) == 2 && bytes.Equal(pair[0], user) &&
bytes.Equal(pair[1], passwd) {
// 執(zhí)行被裝飾的函數(shù)
f(w, r)
return
}
}
}
// 認(rèn)證失敗,提示 401 Unauthorized
// Restricted 可以改成其他的值
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
// 401 狀態(tài)碼
w.WriteHeader(http.StatusUnauthorized)
}
}
func main() {
addr := flag.String("addr", "0.0.0.0:8080", "服務(wù)綁定地址端口")
user := flag.String("user", "", "http認(rèn)證用戶名(如果用戶名為空,則不需要認(rèn)證)")
psw := flag.String("psw", "", "http認(rèn)證密碼")
root := flag.String("root", "./upload/", "文件服務(wù)根目錄")
flag.Parse()
os.Mkdir(*root, 0777)
http_user := []byte(*user)
http_psw := []byte(*psw)
log.Printf("http server listen on %v \n", *addr)
if *user != "" {
http.HandleFunc("/v1/file_upload", BasicAuth(upload, http_user, http_psw))
} else {
http.HandleFunc("/v1/file_upload", upload)
}
http.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir(*root))))
err := http.ListenAndServe(*addr, nil)
if err != nil {
log.Printf("%v", err)
}
}
網(wǎng)頁上傳
新建文件upload.html放到http服務(wù)器root目錄。例如upload文件夾
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>go 上傳test</title>
</head>
<body>
<form method="POST" action="/v1/file_upload" enctype="multipart/form-data" >
<input type="file" name="uploadfile" />
<input type="submit" value="上傳">
</form>
</body>
</html>
文章來源:http://www.zghlxwxcb.cn/news/detail-512494.html
參考
《如何為 HTTP Server 增加 HTTP Basic Auth 》文章來源地址http://www.zghlxwxcb.cn/news/detail-512494.html
到了這里,關(guān)于三分鐘用Golang搭建一個(gè)HTTP文件上傳下載服務(wù)器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!