初步实现文件上传与下载
This commit is contained in:
parent
794bd74337
commit
d6f618888d
|
|
@ -1,4 +1,5 @@
|
||||||
data/*
|
data/*
|
||||||
go.sum
|
go.sum
|
||||||
*.exe
|
*.exe
|
||||||
leveldb-demo
|
leveldb-demo
|
||||||
|
upload/
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
package gin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"myschools.me/yyjishu/yy-base/redis"
|
||||||
|
)
|
||||||
|
|
||||||
|
//从redis中认证用户
|
||||||
|
func AuthUser() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
token := c.GetHeader("Authorization")
|
||||||
|
claims := cacheGet(&token)
|
||||||
|
if claims == nil {
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Set("user", claims)
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//从redis中获取用户信息,最佳实践经验建议把此代码放service层
|
||||||
|
func cacheGet(token *string) interface{} {
|
||||||
|
var user interface{}
|
||||||
|
b, err := redis.GetBytes(token)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(*b, &user); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &user
|
||||||
|
}
|
||||||
|
|
||||||
|
// gin拦截,基于微服务的拦截
|
||||||
|
// func AuthUserBS() gin.HandlerFunc {
|
||||||
|
// return func(c *gin.Context) {
|
||||||
|
// token := c.GetHeader("Authorization")
|
||||||
|
// claims := userAuthWithGrpc(&token)
|
||||||
|
// if claims == nil {
|
||||||
|
// yy.RespUnauth(c, "token无效或过期,请重新登录", nil, nil)
|
||||||
|
// c.Abort()
|
||||||
|
// }
|
||||||
|
// c.Set("user", claims)
|
||||||
|
// c.Next()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func userAuthWithGrpc(token *string) *yy.UserClaims {
|
||||||
|
// srv, err := consul.FindService("oauth", "v1")
|
||||||
|
// if err != nil {
|
||||||
|
// logrus.WithFields(logrus.Fields{
|
||||||
|
// "func": "userAuthWithGrpc",
|
||||||
|
// }).Errorf("consul.FindServer: %s", err.Error())
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
// defer srv.Close()
|
||||||
|
// client := pb.NewCertificationClient(srv)
|
||||||
|
// resp, err := client.Auth(context.Background(), &pb.CertificationAuthRequest{
|
||||||
|
// Token: *token,
|
||||||
|
// })
|
||||||
|
// if err != nil {
|
||||||
|
// logrus.WithFields(logrus.Fields{
|
||||||
|
// "func": "userAuthWithGrpc",
|
||||||
|
// }).Errorf("client.Auth: %s", err.Error())
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
// if resp.Result == "ok" {
|
||||||
|
// r := &yy.UserClaims{}
|
||||||
|
// if err := json.Unmarshal(resp.Data.Value, r); err != nil {
|
||||||
|
// logrus.WithFields(logrus.Fields{
|
||||||
|
// "func": "userAuthWithGrpc",
|
||||||
|
// }).Errorf("json.Unmarshal: %s", err.Error())
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
// return r
|
||||||
|
// }
|
||||||
|
// logrus.WithFields(logrus.Fields{
|
||||||
|
// "func": "userAuthWithGrpc",
|
||||||
|
// }).Warnln("nil")
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package gin
|
||||||
|
|
||||||
|
//GIN 配置
|
||||||
|
type Config struct {
|
||||||
|
RootPath string
|
||||||
|
Addr string
|
||||||
|
Port int
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
package gin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Service(conf *Config) {
|
||||||
|
if conf == nil {
|
||||||
|
conf = &Config{
|
||||||
|
RootPath: "/",
|
||||||
|
Addr: "0.0.0.0",
|
||||||
|
Port: 80,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
router := gin.New()
|
||||||
|
routerSetup(router, &conf.RootPath)
|
||||||
|
s := &http.Server{
|
||||||
|
Addr: fmt.Sprintf("%s:%d", conf.Addr, conf.Port),
|
||||||
|
Handler: router,
|
||||||
|
ReadTimeout: 10 * time.Second,
|
||||||
|
WriteTimeout: 10 * time.Second,
|
||||||
|
MaxHeaderBytes: 1 << 20,
|
||||||
|
}
|
||||||
|
log.Printf("start service on %s", fmt.Sprintf("%s:%d", conf.Addr, conf.Port))
|
||||||
|
log.Fatal(s.ListenAndServe())
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package gin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"myschools.me/suguo/leveldb-demo/handler"
|
||||||
|
)
|
||||||
|
|
||||||
|
//路由配置
|
||||||
|
func routerSetup(router *gin.Engine, rootpath *string) {
|
||||||
|
router.Use(gin.Recovery())
|
||||||
|
|
||||||
|
r := router.Group(fmt.Sprintf("/%s", *rootpath))
|
||||||
|
{
|
||||||
|
r.POST(`/upload`, handler.FileUpload)
|
||||||
|
r.POST(`/update`, handler.FileUpdate)
|
||||||
|
r.POST(`/delete`, handler.FileDelete)
|
||||||
|
r.GET(`/get/:id`, handler.FileGet)
|
||||||
|
}
|
||||||
|
}
|
||||||
31
go.mod
31
go.mod
|
|
@ -1,8 +1,33 @@
|
||||||
module myschools.me/suguo/leveldb-demo
|
module myschools.me/suguo/leveldb-demo
|
||||||
|
|
||||||
go 1.18
|
go 1.17
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/gin-gonic/gin v1.7.4
|
||||||
github.com/syndtr/goleveldb v1.0.0 // indirect
|
github.com/gofrs/uuid v4.2.0+incompatible
|
||||||
|
github.com/sirupsen/logrus v1.8.1
|
||||||
|
github.com/syndtr/goleveldb v1.0.0
|
||||||
|
myschools.me/yyjishu/yy-base v0.16.133
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
|
github.com/go-playground/locales v0.14.0 // indirect
|
||||||
|
github.com/go-playground/universal-translator v0.18.0 // indirect
|
||||||
|
github.com/go-playground/validator/v10 v10.9.0 // indirect
|
||||||
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
|
github.com/gomodule/redigo v1.8.5 // indirect
|
||||||
|
github.com/google/uuid v1.1.2 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/ugorji/go/codec v1.2.6 // indirect
|
||||||
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0 // indirect
|
||||||
|
golang.org/x/text v0.3.7 // indirect
|
||||||
|
google.golang.org/protobuf v1.27.1 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"myschools.me/suguo/leveldb-demo/service"
|
||||||
|
"myschools.me/yyjishu/yy-base/yy"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FileUpload(c *gin.Context) {
|
||||||
|
reqid := yy.NewRequestID()
|
||||||
|
fs, fh, err := c.Request.FormFile("file")
|
||||||
|
if err != nil {
|
||||||
|
yy.RespBadRequest(c, "上传文件获取失败", err, &reqid)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer fs.Close()
|
||||||
|
payload, err := ioutil.ReadAll(fs)
|
||||||
|
if err != nil {
|
||||||
|
yy.RespBadRequest(c, "上传文件中断", err, &reqid)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if fh.Header.Get("Content-Type") != "image/png" {
|
||||||
|
yy.RespBadRequest(c, "文件类型不支持", nil, &reqid)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ret, err := service.FileUpload(&payload)
|
||||||
|
if err != nil {
|
||||||
|
yy.RespInternalServerError(c, "上传失败", err, &reqid)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
yy.RespSuccess(c, "ok", gin.H{
|
||||||
|
"id": *ret,
|
||||||
|
}, &reqid)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func FileGet(c *gin.Context) {
|
||||||
|
reqid := yy.NewRequestID()
|
||||||
|
id := c.Param("id")
|
||||||
|
data, err := service.FileGet(&id)
|
||||||
|
if err != nil {
|
||||||
|
yy.RespInternalServerError(c, "获取文件失败", err, &reqid)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Writer.Write(*data)
|
||||||
|
c.Writer.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
func FileUpdate(c *gin.Context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func FileDelete(c *gin.Context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
@url=http://127.0.0.1:8080/assets/file
|
||||||
|
@createdAt = {{$datetime iso8601}}
|
||||||
|
|
||||||
|
###
|
||||||
|
POST {{url}}/upload HTTP/1.1
|
||||||
|
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
|
||||||
|
|
||||||
|
------WebKitFormBoundary7MA4YWxkTrZu0gW
|
||||||
|
Content-Disposition: form-data; name="text"
|
||||||
|
|
||||||
|
title
|
||||||
|
------WebKitFormBoundary7MA4YWxkTrZu0gW
|
||||||
|
Content-Disposition: form-data; name="file"; filename="1.png"
|
||||||
|
Content-Type: image/png
|
||||||
|
|
||||||
|
< /home/suguo/Pictures/kindeditor_201907201649420191.jpg
|
||||||
|
------WebKitFormBoundary7MA4YWxkTrZu0gW--
|
||||||
|
|
||||||
|
###
|
||||||
|
GET {{url}}/get/1ecb19989cd76cf69cdae53c0efeef79 HTTP/1.1
|
||||||
45
main.go
45
main.go
|
|
@ -1,37 +1,28 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"context"
|
||||||
"log"
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/syndtr/goleveldb/leveldb"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/syndtr/goleveldb/leveldb/opt"
|
"myschools.me/suguo/leveldb-demo/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
db, err := leveldb.OpenFile("./data", nil)
|
gin.Service(&gin.Config{
|
||||||
if err != nil {
|
RootPath: "assets/file",
|
||||||
log.Fatal(err)
|
Addr: "0.0.0.0",
|
||||||
}
|
Port: 8080,
|
||||||
defer db.Close()
|
|
||||||
for i := 0; i < 50; i++ {
|
|
||||||
if err := db.Put([]byte(fmt.Sprintf("hello %d", i)), []byte("a hello world."), nil); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret, err := db.Has([]byte("hello 49"), &opt.ReadOptions{
|
|
||||||
DontFillCache: false,
|
|
||||||
Strict: 0,
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println(ret)
|
|
||||||
|
|
||||||
val, err := db.Get([]byte("hello 4"), nil)
|
// 服务停止相应
|
||||||
if err != nil {
|
c := make(chan os.Signal, 1)
|
||||||
log.Fatal(err)
|
signal.Notify(c, os.Interrupt)
|
||||||
}
|
<-c
|
||||||
fmt.Println(string(val))
|
_, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
logrus.Println("file storage service shutting down")
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gofrs/uuid"
|
||||||
|
"github.com/syndtr/goleveldb/leveldb"
|
||||||
|
"github.com/syndtr/goleveldb/leveldb/opt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
storagepath string = "./upload"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
sp := os.Getenv("p")
|
||||||
|
if sp != "" {
|
||||||
|
storagepath = sp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func FileGet(id *string) (*[]byte, error) {
|
||||||
|
db, err := leveldb.OpenFile(storagepath, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
ret, err := db.Has([]byte(*id), &opt.ReadOptions{
|
||||||
|
DontFillCache: false,
|
||||||
|
Strict: 0,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("文件不存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ret {
|
||||||
|
return nil, errors.New("文件不存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
val, err := db.Get([]byte(*id), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &val, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FileUpload(payload *[]byte) (*string, error) {
|
||||||
|
db, err := leveldb.OpenFile(storagepath, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
key := strings.ReplaceAll(uuid.Must(uuid.NewV6()).String(), "-", "")
|
||||||
|
if err := db.Put([]byte(key), *payload, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FileUpdate() {
|
||||||
|
db, err := leveldb.OpenFile(storagepath, nil)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
ret, err := db.Has([]byte("hello 49"), &opt.ReadOptions{
|
||||||
|
DontFillCache: false,
|
||||||
|
Strict: 0,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(ret)
|
||||||
|
|
||||||
|
val, err := db.Get([]byte("hello 4"), nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(string(val))
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue