78.上傳檔案及在伺服器儲存檔案到任意路徑
上傳檔案到伺服器是一個常用的操作,而在伺服器上儲存檔案就需要多多用心了。因為你不可能只在一個路徑裡儲存檔案,所以需要實踐一下儲存檔案到任意位置。當然,前提是你的應用程式有這樣的操作許可權。
首先建立一個main.go檔案,作為專案的起點。並使用一個網頁模板JoelUploadFile.html,作為操作介面。

程式碼目錄結構
在main檔案中,準備好頁面路徑、上傳路徑、檔案訪問路徑等,及相對應函式
/** * CofoxS * @Author:Jian Junbo * @Email:[email protected] * @Create:2019/3/30 22:25 * Copyright (c) 2019 Jian Junbo All rights reserved. * * Description: */ package main import ( "fmt" "goHttps/uilFileSys" "html/template" "log" "net/http" ) func main() { fmt.Println("Hello Moon!") log.Println("隨意指定檔案儲存路徑!") //--頁面路徑 http.HandleFunc("/", IndexHandler) //--上傳檔案 http.HandleFunc("/fileSys/tmpUpload/", uilFileSys.FileTmpUpload) //----上傳檔案 http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("tmp")))) websitename := ":90" http.ListenAndServe(websitename, nil) } func IndexHandler(writer http.ResponseWriter, request *http.Request) { //取消獲取facicon.ico的訪問 if request.RequestURI == "/facicon.ico" { return } //---------繫結模板頁 begin------------- t, err := template.ParseFiles("./templatefile/JoelUploadFile.html") if err != nil { fmt.Println("發生了錯誤!") fmt.Fprintln(writer, err) } t.ExecuteTemplate(writer, "JoelUploadFile.html", "") //---------繫結模板頁 end--------------- }
需要繫結的模板檔案 JoelUploadFile.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>企業上傳檔案</title> <style type="text/css"> input{ line-height: 20px; padding-left: 2px; padding-right: 2px; margin-left: 2px; margin-right: 2px; background-color: #eaf4fc; border-color: #b5c1e4; border-width: 1px; border-style: solid; border-radius: 3px; } /*上傳檔案*/ .file { position: relative; display: inline-block; background: #D0EEFF; border: 1px solid #99D3F5; border-radius: 4px; padding: 4px 12px; overflow: hidden; color: #1E88C7; text-decoration: none; text-indent: 0; line-height: 20px; } .file input { position: absolute; font-size: 100px; right: 0; top: 0; opacity: 0; } .file:hover { background: #AADFFD; border-color: #78C3F3; color: #004974; text-decoration: none; } </style> <script type="text/javascript"> /*同步資料*/ function synkFile(srcObj, showObj, newObj) { var srcO = document.getElementById(srcObj); var showO = document.getElementById(showObj); var new0 = document.getElementById(newObj); /*if (srcO.value.length > 0) { showO.value = srcO.value; } */ // showO.value = ""; new0.innerText = ""; for (var i = 0; i < srcO.files.length; i++) { // showO.value += srcO.files[i].name + "|"; new0.innerText += srcO.files[i].name + "|\r\n"; } } /*儲存修改資料*/ function saveF() { var frm = document.getElementById("formSave"); var u_id = document.getElementById("u_Id"); if (u_id.value.length <= 0) { alert('\'流水號\'丟失!'); return; } frm.submit(); } </script> </head> <body> <div>企業上傳檔案,按照“平臺》企業編號》系統》年月日”來儲存檔案,檔名使用生成時間</div> <div> <form id="formSave"enctype="multipart/form-data" action="/fileSys/tmpUpload/" method="post"> <input id="u_Id" name="u_Id" type="text" value="joel" style="width: 500px; display: none;" readonly> <a href="javascript:;" class="file">上傳附件<input type="file" id="uploadfile" name="uploadfile" multiple style="cursor: pointer" onchange="synkFile('uploadfile','u_ElectranicAttachment','new_ElectranicAttachment')"></a> <label id="show_ElectranicAttachment"></label> <label id="new_ElectranicAttachment"></label> <input id="u_ElectranicAttachment" name="u_ElectranicAttachment" type="text" value="" style="display: none"> <div><input type="button" value="儲存"onclick="saveF()"></div> </form> </div> </body> </html>
實現上傳功能的函式
/** * CofoxS * @Author:Jian Junbo * @Email:[email protected] * @Create:2019/3/31 23:27 * Copyright (c) 2019 Jian Junbo All rights reserved. * * Description:企業檔案管理 */ package uilFileSys import ( "cofoxWebPlatform/platform/lib" "cofoxWebPlatform/platform/model" "encoding/json" "fmt" "io" "net/http" "os" "path" ) //上傳檔案到臨時檔案路徑,前提條件是當前使用者是線上使用者 func FileTmpUpload(writer http.ResponseWriter, request *http.Request){ //接收資料 keyId := request.FormValue("keyId")//key身份Id //get a ref to the parsedmultipart form m := request.MultipartForm //get the *fileheaders files := m.File["uploadfile"] for i,_ := range files{ //save the file as filename filename := lib.JoelGetNowFullTimeNumber() +path.Ext(files[i].Filename) //for each fileheader, get a handle to the actual file file, err := files[i].Open() defer file.Close() if err != nil { http.Error(writer, err.Error(), http.StatusInternalServerError) return } //create destination file making sure the path is writeable. dst, err := os.Create("./tmp/" + filename) defer dst.Close() if err != nil { http.Error(writer, err.Error(), http.StatusInternalServerError) return } //copy the uploaded file to the destination file if _, err := io.Copy(dst, file); err != nil { http.Error(writer, err.Error(), http.StatusInternalServerError) return } tmpfile := dst.Name()// 寫入儲存檔案的位置和檔名 lib.JoelLog(keyId,tmpfile)//服務端輸出 resultValue := model.JoelBaseAskResultNormal{} resultValue.AskResult = tmpfile back,_ := json.Marshal(resultValue) fmt.Fprint(writer,string(back)) //返回客端資料 } }
執行此程式

伺服器顯示

瀏覽器顯示
點選“上傳附件”,選擇要上傳的檔案。

選擇一個圖片檔案
點選“儲存”按鈕,激發js的saveF()函式,提交form到伺服器

一般都會順帶提交一些其他資料,例如:u_Id
提交後,檔案儲存到 "/tmp/" 路徑,這個路徑在當前程式的根上。

已上傳到伺服器的檔案

伺服器返回的json串
下面可以指定儲存的其他路徑
當前檔案儲存的位置是 tmp 路徑,是在 \uilFileSys\EntFileMS.go 中定義的
//create destination file making sure the path is writeable. dst, err := os.Create("./tmp/" + filename)
用windows系統來舉例,如果我希望檔案儲存在另一個位置,比如:e盤,這行程式碼只需要修改為
//create destination file making sure the path is writeable. dst, err := os.Create("e://" + filename)
如果,你上傳之後,還想能夠通過瀏覽器訪問到這個檔案,那麼在 main.go 中,有這樣的一行程式碼
//----上傳檔案 http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("tmp"))))
你需要把它改成
//----上傳檔案 http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("e:\\"))))
至此,大功告成!你已經可以把檔案上傳到 e 盤了。
在此基礎上,你應該可以動態的指定每次上傳檔案的物理路徑了。