惊风破浪的博客
PHP
MySQL
Redis
Linux
算法与设计模式
杂项
Golang
登录
学习Go实现上传文件,下载等接口
1个月前 ⋅
0
- 实现,上传文件,获取元数据信息,下载文件,更新元信息,文件删除等接口;信息暂时放内存,容易丢失; `报gopath错误先执行git mod init 先执行` - 文件目录,和main.go接口地址  - handler目录 - handler.go 代码 ```go package handler import ( "encoding/json" "fmt" "io" "io/ioutil" "net/http" "os" "filestore-server/meta" "filestore-server/util" "time" ) //处理文件上传 func UploadHandler(w http.ResponseWriter,r *http.Request) { if r.Method == "GET" { data, err := ioutil.ReadFile("./static/view/index.html") if err != nil { io.WriteString(w, "上传错误") } io.WriteString(w, string(data)) //返回上传页面 } else if r.Method == "POST" { //接收文件流存储到本地目录 file, head, err := r.FormFile("file") if err != nil { fmt.Printf("failed to get data,err %s\n", err.Error()) return } defer file.Close() fileMeta :=meta.FileMeta{ FileName: head.Filename, Location: "./tmp/" + head.Filename, UploadAt: time.Now().Format("2006 01-02 12:30:22"), } newFile, err := os.Create(fileMeta.Location) if err != nil { fmt.Printf("Failed to create file,err %s\n", err.Error()) return } defer newFile.Close() fileMeta.Filesize, err = io.Copy(newFile, file) if err != nil { fmt.Printf("Failed to save data into file err %s\n",err.Error()) return } newFile.Seek(0,0) fileMeta.FileSha1 = util.FileSha1(newFile) //哈希值 meta.UploadFileMeta(fileMeta) //新增,更新元数据 http.Redirect(w,r,"/file/upload/suc",http.StatusFound) } } //上传完成 func UploadSunHandler(w http.ResponseWriter,r *http.Request) { io.WriteString(w,"上传成功") } //获取元数据信息 func GetFileMetaHandler(w http.ResponseWriter,r *http.Request) { r.ParseForm() filehash := r.Form["filehash"][0] //获取文件hash fMeta := meta.GetFileMeta(filehash) //通过hash获取元数信息 data, err := json.Marshal(fMeta) //转换为json if err!=nil { w.WriteHeader(http.StatusInternalServerError) return } w.Write(data) } //更新元信息接口(重命名) func FileMetaUpdateHandle(w http.ResponseWriter,r *http.Request) { r.ParseForm() opType := r.Form.Get("op") filesha1 := r.Form.Get("filehash") NewFileName := r.Form.Get("filename") if opType != "0" { w.WriteHeader(http.StatusForbidden) return } if r.Method != "POST" { w.WriteHeader(http.StatusMethodNotAllowed) } curFileMeta := meta.GetFileMeta(filesha1) //通过sha1值获取文件的元信息对象 curFileMeta.FileName = NewFileName //接口的哈希值 meta.UploadFileMeta(curFileMeta) //更新元信息到内存 w.WriteHeader(http.StatusOK) data, err := json.Marshal(curFileMeta) if err != nil { w.WriteHeader(http.StatusInternalServerError) } w.WriteHeader(http.StatusOK) w.Write(data) } //删除文件 func FileDeleteHandle(w http.ResponseWriter,r *http.Request) { r.ParseForm() filesha1 := r.Form.Get("filehash") fMeta := meta.GetFileMeta(filesha1) os.Remove(fMeta.Location) meta.RemoveFileMeta(filesha1) w.WriteHeader(http.StatusOK) } //文件下载 func DownloadHandler(w http.ResponseWriter,r *http.Request) { r.ParseForm() fsha1 := r.Form.Get("filehash") fm := meta.GetFileMeta(fsha1) //哈希值从内存拿到信息 f, err := os.Open(fm.Location) //打开文件 if err != nil { //判断是否能打开 w.WriteHeader(http.StatusInternalServerError) return } defer f.Close() data, err := ioutil.ReadAll(f) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } w.Header().Set("Content-Type","application/octect-stream") w.Header().Set("Content-disposition","attachment;filename=\""+fm.FileName+"\"") w.Write(data) } ``` - meta目录 - filemeta.go //更新元信息,删除文件,存储元信息 ```go package meta //文件元信息 type FileMeta struct { FileSha1 string FileName string Filesize int64 Location string UploadAt string } var fileMetas map[string]FileMeta func init() { fileMetas = make(map[string]FileMeta) } //新增/更新文件元信息 func UploadFileMeta(fmeta FileMeta) { fileMetas[fmeta.FileSha1] = fmeta } //通过sha1值获取文件的元信息对象 func GetFileMeta(fileSha1 string)FileMeta { return fileMetas[fileSha1] } //通过哈希值删除文件 func RemoveFileMeta(fileSha1 string) { delete(fileMetas, fileSha1) } ``` - util目录 - util.go //封装生成hash文件,转json数据方法 ```go package util import ( "crypto/md5" "crypto/sha1" "encoding/hex" "hash" "io" "os" "path/filepath" ) type Sha1Stream struct { _sha1 hash.Hash } func (obj *Sha1Stream) Update(data []byte) { if obj._sha1 == nil { obj._sha1 = sha1.New() } obj._sha1.Write(data) } func (obj *Sha1Stream) Sum() string { return hex.EncodeToString(obj._sha1.Sum([]byte(""))) } func Sha1(data []byte) string { _sha1 := sha1.New() _sha1.Write(data) return hex.EncodeToString(_sha1.Sum([]byte(""))) } func FileSha1(file *os.File) string { _sha1 := sha1.New() io.Copy(_sha1, file) return hex.EncodeToString(_sha1.Sum(nil)) } func MD5(data []byte) string { _md5 := md5.New() _md5.Write(data) return hex.EncodeToString(_md5.Sum([]byte(""))) } func FileMD5(file *os.File) string { _md5 := md5.New() io.Copy(_md5, file) return hex.EncodeToString(_md5.Sum(nil)) } func PathExists(path string) (bool, error) { _, err := os.Stat(path) if err == nil { return true, nil } if os.IsNotExist(err) { return false, nil } return false, err } func GetFileSize(filename string) int64 { var result int64 filepath.Walk(filename, func(path string, f os.FileInfo, err error) error { result = f.Size() return nil }) return result } ```
回复
发布文章
友情链接
Mr.Zhu
Swoole
PHP官网
菜鸟教程
Go语言中文网
implode
数据结构与算法