go 文件服务(读取须权限)
1 package Network 2 3 import ( 4 "encoding/base64" 5 "encoding/json" 6 "net/http" 7 "os" 8 "strings" 9 "time" 10 "token" 11 ) 12 13 func getFile(w http.ResponseWriter, req *http.Request) { 14 var ( 15 code int = Success 16 msg string = "" 17 result interface{} = nil 18 httpCode int = http.StatusOK 19 ) 20 defer func() { 21 w.WriteHeader(httpCode) 22 if httpCode != http.StatusOK { 23 writeHTTPResult(w, code, msg, result) 24 } 25 }() 26 Token := req.FormValue("token") 27 user, ok := token.GetUser(Token) 28 if !ok { 29 httpCode = http.StatusForbidden 30 code = errNoPermission 31 msg = "token 无效" 32 return 33 } 34 35 httpCode, fileInfo, base64FileName := Decode(req) 36 37 if user.ID == fileInfo.ReceiverID || user.ID == fileInfo.SenderID { 38 httpCode, code, msg = WriteFile(w, req, fileInfo, base64FileName) 39 return 40 } 41 42 code, msg = IsGroupID(fileInfo.ReceiverID) 43 if code != Success { 44 httpCode = http.StatusForbidden 45 if code == errInvalidID { 46 code = errNoPermission 47 msg = "you have no permission to get this file" 48 } 49 return 50 } 51 52 code, msg = IsGroupMember(user.ID, fileInfo.ReceiverID) 53 if code != Success { 54 httpCode = http.StatusForbidden 55 if code == errInvalidID { 56 code = errNoPermission 57 msg = "you have no permission to get this file" 58 } 59 return 60 } 61 62 httpCode, code, msg = WriteFile(w, req, fileInfo, base64FileName) 63 return 64 65 } 66 func WriteFile(w http.ResponseWriter, req *http.Request, fileInfo *FileInfo, base64FileName string) (httpCode int, code int, msg string) { 67 file, err := os.Open(publicFileDir + "/" + fileInfo.FileType + "/" + base64FileName) 68 if err != nil { 69 httpCode = http.StatusNotFound 70 code = errFileNotFound 71 msg = err.Error() 72 return 73 } 74 defer file.Close() 75 w.Header().Set("Filename", fileInfo.FileName) 76 http.ServeContent(w, req, fileInfo.FileName, time.Time{}, file) 77 return http.StatusOK, Success, "" 78 } 79 80 func Decode(req *http.Request) (httpCode int, fileInfo *FileInfo, base64FileName string) { 81 fileInfo = new(FileInfo) 82 URL := strings.Split(req.URL.Path, "/") 83 if len(URL) == 0 { 84 return http.StatusNotFound, nil, base64FileName 85 } 86 base64FileName = URL[len(URL)-1] 87 fileName, err := base64.StdEncoding.DecodeString(base64FileName) 88 if err != nil { 89 return http.StatusBadRequest, nil, base64FileName 90 } 91 err = json.Unmarshal(fileName, fileInfo) 92 if err != nil { 93 return http.StatusForbidden, nil, base64FileName 94 } 95 return http.StatusOK, fileInfo, base64FileName 96 }
1 func getFile(uri string, fileName string) error { 2 resp, err := http.Get(uri) 3 if err != nil { 4 return err 5 } 6 defer resp.Body.Close() 7 if resp.StatusCode != http.StatusOK { 8 body, err := ioutil.ReadAll(resp.Body) 9 if err != nil { 10 return err 11 } 12 return errors.New("statusCode:" + fmt.Sprint(resp.StatusCode) + "\n" + string(body)) 13 } 14 if fileName == "" { 15 if resp.Header["Filename"] != nil { 16 fileName = resp.Header["Filename"][0] 17 } else { 18 fileName = "notFound" 19 } 20 } 21 icon, err := os.Create(fileName) 22 if err != nil { 23 return err 24 } 25 _, err = io.Copy(icon, resp.Body) 26 if err != nil { 27 return err 28 } 29 logs.Print(resp.Header) 30 return nil 31 }
这里由于http response的body完全是文件的二进制流,所以Filename要么是前端定义,要么是后端通过header返回
文件的url是一个base64编码的字符串,包含验证读取权限相关的所有信息和源文件名(服务器存文件时用的是base64编码作为文件名)