增加文件上传及下载
parent
d93041180a
commit
3baef6449e
212
README.md
212
README.md
|
@ -3,28 +3,28 @@ go web脚手架, [数据库及表结构](./resource/sql/weekly_report.sql)
|
|||
|
||||
# [web框架gin](https://gin-gonic.com/zh-cn/docs/introduction/)
|
||||
## 特性
|
||||
#### 快速
|
||||
- 快速
|
||||
基于 Radix 树的路由,小内存占用。没有反射。可预测的 API 性能。
|
||||
|
||||
#### 支持中间件
|
||||
- 支持中间件
|
||||
传入的 HTTP 请求可以由一系列中间件和最终操作来处理。 例如:Logger,Authorization,GZIP,最终操作 DB。
|
||||
|
||||
#### Crash 处理
|
||||
- Crash 处理
|
||||
Gin 可以 catch 一个发生在 HTTP 请求中的 panic 并 recover 它。这样,你的服务器将始终可用。例如,你可以向 Sentry 报告这个 panic!
|
||||
|
||||
#### JSON 验证
|
||||
- JSON 验证
|
||||
Gin 可以解析并验证请求的 JSON,例如检查所需值的存在。
|
||||
|
||||
#### 路由组
|
||||
- 路由组
|
||||
更好地组织路由。是否需要授权,不同的 API 版本…… 此外,这些组可以无限制地嵌套而不会降低性能。
|
||||
|
||||
#### 错误管理
|
||||
- 错误管理
|
||||
Gin 提供了一种方便的方法来收集 HTTP 请求期间发生的所有错误。最终,中间件可以将它们写入日志文件,数据库并通过网络发送。
|
||||
|
||||
#### 内置渲染
|
||||
- 内置渲染
|
||||
Gin 为 JSON,XML 和 HTML 渲染提供了易于使用的 API。
|
||||
|
||||
#### 可扩展性
|
||||
- 可扩展性
|
||||
新建一个中间件非常简单,去查看 [示例代码](https://gin-gonic.com/zh-cn/docs/examples/) 吧。
|
||||
|
||||
## 服务创建及启动
|
||||
|
@ -72,8 +72,153 @@ func main() {
|
|||
}
|
||||
```
|
||||
|
||||
# [gorm](https://gorm.io/zh_CN/docs/index.html)
|
||||
## 概述
|
||||
- 全功能 ORM
|
||||
- 关联 (Has One,Has Many,Belongs To,Many To Many,多态,单表继承)属于、多对多、多态、单表继承)
|
||||
- Create,Save,Update,Delete,Find 中钩子方法保存/更新/删除/查找)
|
||||
- 支持 Preload、Joins 的预加载,Joins
|
||||
- 事务,嵌套事务,Save Point,Rollback To Saved Point、回滚到保存点
|
||||
- Context、预编译模式、DryRun 模式DryRun 模式
|
||||
- 批量插入,FindInBatches,Find/Create with Map,使用 SQL 表达式、Context Valuer 进行 CRUDBatches、使用 Map 查找/创建、使用 SQL Expr 和 Context Valuer 进行 CRUD
|
||||
- SQL 构建器,Upsert,数据库锁,Optimizer/Index/Comment Hint,命名参数,子查询、Upsert、锁定、优化器/索引/注释提示、命名参数、子查询
|
||||
- 复合主键,索引,约束
|
||||
- Auto Migration
|
||||
- 自定义 Logger
|
||||
- 灵活的可扩展插件 API:Database Resolver(多数据库,读写分离)、Prometheus…PI:数据库解析器(多个数据库,读/写拆分)/ Prometheus...
|
||||
- 每个特性都经过了测试的重重考验
|
||||
- 开发者友好
|
||||
|
||||
## 模型定义
|
||||
```
|
||||
type User struct {
|
||||
ID uint
|
||||
Name string
|
||||
Email *string
|
||||
Age uint8
|
||||
Birthday *time.Time
|
||||
MemberNumber sql.NullString
|
||||
ActivatedAt sql.NullTime
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
```
|
||||
|
||||
# 通过Swagger测试接口
|
||||
GORM 使用结构体名的 蛇形命名 作为表名。对于结构体 User,根据约定,其表名为 users
|
||||
您可以实现 Tabler 接口来更改默认表名,例如:
|
||||
```
|
||||
type Tabler interface {
|
||||
TableName() string
|
||||
}
|
||||
|
||||
// TableName 会将 User 的表名重写为 `profiles`
|
||||
func (User) TableName() string {
|
||||
return "profiles"
|
||||
}
|
||||
```
|
||||
|
||||
您可以使用 Table 方法临时指定表名,例如:
|
||||
```
|
||||
// 根据 User 的字段创建 `deleted_users` 表
|
||||
db.Table("deleted_users").AutoMigrate(&User{})
|
||||
|
||||
// 从另一张表查询数据
|
||||
var deletedUsers []User
|
||||
db.Table("deleted_users").Find(&deletedUsers)
|
||||
// SELECT * FROM deleted_users;
|
||||
|
||||
db.Table("deleted_users").Where("name = ?", "jinzhu").Delete(&User{})
|
||||
// DELETE FROM deleted_users WHERE name = 'jinzhu';
|
||||
```
|
||||
|
||||
## 连接数据库
|
||||
```
|
||||
import (
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
|
||||
dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
||||
}
|
||||
```
|
||||
|
||||
### 连接池
|
||||
GORM 使用 database/sql 维护连接池
|
||||
```
|
||||
sqlDB, err := db.DB()
|
||||
|
||||
// SetMaxIdleConns 设置空闲连接池中连接的最大数量
|
||||
sqlDB.SetMaxIdleConns(10)
|
||||
|
||||
// SetMaxOpenConns 设置打开数据库连接的最大数量。
|
||||
sqlDB.SetMaxOpenConns(100)
|
||||
|
||||
// SetConnMaxLifetime 设置了连接可复用的最大时间。
|
||||
sqlDB.SetConnMaxLifetime(time.Hour)
|
||||
```
|
||||
|
||||
## CRUD
|
||||
### 基本操作
|
||||
```
|
||||
# 创建记录
|
||||
user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}
|
||||
|
||||
result := db.Create(&user) // 通过数据的指针来创建
|
||||
|
||||
user.ID // 返回插入数据的主键
|
||||
result.Error // 返回 error
|
||||
result.RowsAffected // 返回插入记录的条数
|
||||
----------------------------------------------------------------------
|
||||
|
||||
# 查询
|
||||
// 获取第一条记录(主键升序)
|
||||
db.First(&user)
|
||||
// SELECT * FROM users ORDER BY id LIMIT 1;
|
||||
|
||||
// 获取一条记录,没有指定排序字段
|
||||
db.Take(&user)
|
||||
// SELECT * FROM users LIMIT 1;
|
||||
|
||||
// 获取最后一条记录(主键降序)
|
||||
db.Last(&user)
|
||||
// SELECT * FROM users ORDER BY id DESC LIMIT 1;
|
||||
----------------------------------------------------------------------
|
||||
|
||||
# 更新
|
||||
user.Name = "jinzhu 2"
|
||||
user.Age = 100
|
||||
db.Save(&user)
|
||||
// UPDATE users SET name='jinzhu 2', age=100, birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=111
|
||||
----------------------------------------------------------------------
|
||||
|
||||
# 删除
|
||||
// Email 的 ID 是 `10`
|
||||
db.Delete(&email)
|
||||
// DELETE from emails where id = 10;
|
||||
|
||||
// 带额外条件的删除
|
||||
db.Where("name = ?", "jinzhu").Delete(&email)
|
||||
// DELETE from emails where id = 10 AND name = "jinzhu";
|
||||
----------------------------------------------------------------------
|
||||
```
|
||||
### 创建钩子
|
||||
GORM 允许用户定义的钩子有 BeforeSave, BeforeCreate, AfterSave, AfterCreate 创建记录时将调用这些钩子方法,请参考 Hooks 中关于生命周期的详细信息
|
||||
```
|
||||
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
|
||||
u.UUID = uuid.New()
|
||||
|
||||
if u.Role == "admin" {
|
||||
return errors.New("invalid role")
|
||||
}
|
||||
return
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
# 通过Swagger测试接口, [中文文档](https://github.com/swaggo/swag/blob/master/README_zh-CN.md)
|
||||
[官方地址](https://github.com/swaggo) ,其中包含`swag`可执行程序和`gin-swagger`go web模块, [使用手册](https://github.com/swaggo/gin-swagger)
|
||||
查看地址为: **http://IP:8888/swagger/index.html**
|
||||
|
||||
|
@ -211,7 +356,7 @@ jwt token
|
|||
**用户-角色权限-菜单项|API|资源对应关系图**
|
||||
<br>
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
# 获取菜单项
|
||||
|
@ -480,7 +625,7 @@ x-user-id: 1
|
|||
|
||||
|
||||
|
||||
## 使用[casbin](https://github.com/casbin/casbin) 控制权限
|
||||
# 使用[casbin](https://github.com/casbin/casbin) 控制权限
|
||||
Casbin is a powerful and efficient open-source access control library. It provides support for enforcing authorization based on various access control models.
|
||||
|
||||
可以 [在线](https://casbin.org/editor/) 书写规则:
|
||||
|
@ -521,6 +666,37 @@ results, err := e.BatchEnforce([][]interface{}{{"alice", "data1", "read"}, {"bob
|
|||
|
||||
# 文件上传及下载
|
||||
|
||||
文件上传成功返回:
|
||||
```
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"file": {
|
||||
"ID": 0,
|
||||
"CreatedAt": "0001-01-01T00:00:00Z",
|
||||
"UpdatedAt": "0001-01-01T00:00:00Z",
|
||||
"name": "demo.c",
|
||||
"url": "/Users/zero/Documents/uploads/file/fe01ce2a7fbac8fafaed7c982a04e229_20211102170427.c",
|
||||
"tag": "c",
|
||||
"key": "fe01ce2a7fbac8fafaed7c982a04e229_20211102170427.c"
|
||||
}
|
||||
},
|
||||
"msg": "上传成功"
|
||||
}
|
||||
```
|
||||
|
||||
数据库信息:
|
||||
```
|
||||
mysql> select * from file_upload_and_downloads;
|
||||
+----+---------------------+---------------------+------------+--------+--------------------------------------------------------------------------------------+------+---------------------------------------------------+
|
||||
| id | created_at | updated_at | deleted_at | name | url | tag | key |
|
||||
+----+---------------------+---------------------+------------+--------+--------------------------------------------------------------------------------------+------+---------------------------------------------------+
|
||||
| 3 | 2021-11-02 09:04:27 | 2021-11-02 09:04:27 | NULL | demo.c | /Users/zero/Documents/uploads/file/fe01ce2a7fbac8fafaed7c982a04e229_20211102170427.c | c | fe01ce2a7fbac8fafaed7c982a04e229_20211102170427.c |
|
||||
+----+---------------------+---------------------+------------+--------+--------------------------------------------------------------------------------------+------+---------------------------------------------------+
|
||||
```
|
||||
|
||||
|
||||
|
||||
# 反射reflect
|
||||
[官方文档](https://pkg.go.dev/reflect)
|
||||
|
||||
|
@ -585,6 +761,20 @@ Sets the location for time.Time values (when using parseTime=true). "Local" sets
|
|||
github.com/casbin/gorm-adapter/v3 v3.0.2
|
||||
|
||||
|
||||
#### 查看http请求详情
|
||||
|
||||
通过查看gin.Context>>Request>>(Body io.ReadCloser)>>src>>R>>buf=>点击view就能看到http详情。
|
||||
|
||||
<br>
|
||||
<div align=center>
|
||||
<img src="./resource/md_res/gin-http-res.jpg" width="70%" height="70%" title="Go Http请求"></img>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
"goweb-gin-demo/global"
|
||||
"goweb-gin-demo/model/common/response"
|
||||
webRes "goweb-gin-demo/model/web/response"
|
||||
"goweb-gin-demo/utils"
|
||||
)
|
||||
|
||||
// @Tags FileUploadAndDownload
|
||||
// @Summary 断点续传到服务器
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "an example for breakpoint resume, 断点续传示例"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"切片创建成功"}"
|
||||
// @Router /fileUploadAndDownload/breakpointContinue [post]
|
||||
func (u *FileUploadAndDownloadApi) BreakpointContinue(c *gin.Context) {
|
||||
fileMd5 := c.Request.FormValue("fileMd5")
|
||||
fileName := c.Request.FormValue("fileName")
|
||||
chunkMd5 := c.Request.FormValue("chunkMd5")
|
||||
chunkNumber, _ := strconv.Atoi(c.Request.FormValue("chunkNumber"))
|
||||
chunkTotal, _ := strconv.Atoi(c.Request.FormValue("chunkTotal"))
|
||||
_, FileHeader, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
global.GLOBAL_LOG.Error("接收文件失败!", zap.Any("err", err))
|
||||
response.FailWithMessage("接收文件失败", c)
|
||||
return
|
||||
}
|
||||
f, err := FileHeader.Open()
|
||||
if err != nil {
|
||||
global.GLOBAL_LOG.Error("文件读取失败!", zap.Any("err", err))
|
||||
response.FailWithMessage("文件读取失败", c)
|
||||
return
|
||||
}
|
||||
defer func(f multipart.File) {
|
||||
err := f.Close()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}(f)
|
||||
cen, _ := ioutil.ReadAll(f)
|
||||
if !utils.CheckMd5(cen, chunkMd5) {
|
||||
global.GLOBAL_LOG.Error("检查md5失败!", zap.Any("err", err))
|
||||
response.FailWithMessage("检查md5失败", c)
|
||||
return
|
||||
}
|
||||
err, file := fileUploadAndDownloadService.FindOrCreateFile(fileMd5, fileName, chunkTotal)
|
||||
if err != nil {
|
||||
global.GLOBAL_LOG.Error("查找或创建记录失败!", zap.Any("err", err))
|
||||
response.FailWithMessage("查找或创建记录失败", c)
|
||||
return
|
||||
}
|
||||
err, pathc := utils.BreakPointContinue(cen, fileName, chunkNumber, chunkTotal, fileMd5)
|
||||
if err != nil {
|
||||
global.GLOBAL_LOG.Error("断点续传失败!", zap.Any("err", err))
|
||||
response.FailWithMessage("断点续传失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
if err = fileUploadAndDownloadService.CreateFileChunk(file.ID, pathc, chunkNumber); err != nil {
|
||||
global.GLOBAL_LOG.Error("创建文件记录失败!", zap.Any("err", err))
|
||||
response.FailWithMessage("创建文件记录失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("切片创建成功", c)
|
||||
}
|
||||
|
||||
// @Tags FileUploadAndDownload
|
||||
// @Summary 查找文件
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "Find the file, 查找文件"qqq
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查找成功"}"
|
||||
// @Router /fileUploadAndDownload/findFile [post]
|
||||
func (u *FileUploadAndDownloadApi) FindFile(c *gin.Context) {
|
||||
fileMd5 := c.Query("fileMd5")
|
||||
fileName := c.Query("fileName")
|
||||
chunkTotal, _ := strconv.Atoi(c.Query("chunkTotal"))
|
||||
err, file := fileUploadAndDownloadService.FindOrCreateFile(fileMd5, fileName, chunkTotal)
|
||||
if err != nil {
|
||||
global.GLOBAL_LOG.Error("查找失败!", zap.Any("err", err))
|
||||
response.FailWithMessage("查找失败", c)
|
||||
} else {
|
||||
response.OkWithDetailed(webRes.FileResponse{File: file}, "查找成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags FileUploadAndDownload
|
||||
// @Summary 创建文件
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "上传文件完成"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"file uploaded, 文件创建成功"}"
|
||||
// @Router /fileUploadAndDownload/breakpointContinueFinish [post]
|
||||
func (b *FileUploadAndDownloadApi) BreakpointContinueFinish(c *gin.Context) {
|
||||
fileMd5 := c.Query("fileMd5")
|
||||
fileName := c.Query("fileName")
|
||||
err, filePath := utils.MakeFile(fileName, fileMd5)
|
||||
if err != nil {
|
||||
global.GLOBAL_LOG.Error("文件创建失败!", zap.Any("err", err))
|
||||
response.FailWithDetailed(webRes.FilePathResponse{FilePath: filePath}, "文件创建失败", c)
|
||||
} else {
|
||||
response.OkWithDetailed(webRes.FilePathResponse{FilePath: filePath}, "文件创建成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags FileUploadAndDownload
|
||||
// @Summary 删除切片
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "删除缓存切片"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"缓存切片删除成功"}"
|
||||
// @Router /fileUploadAndDownload/removeChunk [post]
|
||||
func (u *FileUploadAndDownloadApi) RemoveChunk(c *gin.Context) {
|
||||
fileMd5 := c.Query("fileMd5")
|
||||
fileName := c.Query("fileName")
|
||||
filePath := c.Query("filePath")
|
||||
err := utils.RemoveChunk(fileMd5)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = fileUploadAndDownloadService.DeleteFileChunk(fileMd5, fileName, filePath)
|
||||
if err != nil {
|
||||
global.GLOBAL_LOG.Error("缓存切片删除失败!", zap.Any("err", err))
|
||||
response.FailWithDetailed(webRes.FilePathResponse{FilePath: filePath}, "缓存切片删除失败", c)
|
||||
} else {
|
||||
response.OkWithDetailed(webRes.FilePathResponse{FilePath: filePath}, "缓存切片删除成功", c)
|
||||
}
|
||||
}
|
|
@ -3,10 +3,10 @@ package web
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mojocn/base64Captcha"
|
||||
"go.uber.org/zap"
|
||||
"goweb-gin-demo/global"
|
||||
"goweb-gin-demo/model/common/response"
|
||||
webRes "goweb-gin-demo/model/web/response"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// 当开启多服务器部署时,替换下面的配置,使用redis共享存储验证码
|
||||
|
|
|
@ -8,6 +8,8 @@ type ApiGroup struct {
|
|||
BaseApi
|
||||
JwtApi
|
||||
AuthorityMenuApi
|
||||
FileUploadAndDownloadApi
|
||||
SystemApi
|
||||
}
|
||||
|
||||
var userService = service.ServiceGroupApp.UserService
|
||||
|
@ -15,4 +17,5 @@ var jwtService = service.ServiceGroupApp.JwtService
|
|||
var menuService = service.ServiceGroupApp.MenuService
|
||||
var baseMenuService = service.ServiceGroupApp.BaseMenuService
|
||||
var systemConfigService = service.ServiceGroupApp.SystemConfigService
|
||||
var fileUploadAndDownloadService = service.ServiceGroupApp.FileUploadAndDownloadService
|
||||
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
"goweb-gin-demo/global"
|
||||
"goweb-gin-demo/model/common/request"
|
||||
"goweb-gin-demo/model/common/response"
|
||||
"goweb-gin-demo/model/web"
|
||||
webRes "goweb-gin-demo/model/web/response"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type FileUploadAndDownloadApi struct {
|
||||
}
|
||||
|
||||
// @Tags FileUploadAndDownload
|
||||
// @Summary 上传文件示例
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "上传文件示例"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"上传成功"}"
|
||||
// @Router /fileUploadAndDownload/upload [post]
|
||||
func (u *FileUploadAndDownloadApi) UploadFile(c *gin.Context) {
|
||||
var file web.FileUploadAndDownload
|
||||
noSave := c.DefaultQuery("noSave", "0")
|
||||
_, header, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
global.GLOBAL_LOG.Error("接收文件失败!", zap.Any("err", err))
|
||||
response.FailWithMessage("接收文件失败", c)
|
||||
return
|
||||
}
|
||||
err, file = fileUploadAndDownloadService.UploadFile(header, noSave) // 文件上传后拿到文件路径
|
||||
if err != nil {
|
||||
global.GLOBAL_LOG.Error("修改数据库链接失败!", zap.Any("err", err))
|
||||
response.FailWithMessage("修改数据库链接失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(webRes.ExaFileResponse{File: file}, "上传成功", c)
|
||||
}
|
||||
|
||||
// @Tags FileUploadAndDownload
|
||||
// @Summary 文件下载
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param fileName query string true "待下载的文件名"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"文件下载成功"}"
|
||||
// @Router /fileUploadAndDownload/download [get]
|
||||
func (u *FileUploadAndDownloadApi) DownloadFile(c *gin.Context) {
|
||||
fileName := c.Query("fileName")
|
||||
|
||||
//待下载的文件是存储本地的,如果存储在云盘,直接访问链接即可
|
||||
//如果没有记录,也会报错,record not found
|
||||
err, fileInfo := fileUploadAndDownloadService.FindFile(fileName)
|
||||
|
||||
if err != nil {
|
||||
global.GLOBAL_LOG.Error("文件未找到!", zap.Any("err", err))
|
||||
c.Redirect(http.StatusFound, "/404")
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("Content-Type", "application/octet-stream")
|
||||
c.Header("Content-Disposition", "attachment; filename="+fileInfo.Name)
|
||||
c.Header("Content-Transfer-Encoding", "binary")
|
||||
|
||||
c.File(fileInfo.Url)
|
||||
return
|
||||
}
|
||||
|
||||
// @Tags FileUploadAndDownload
|
||||
// @Summary 删除文件
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body web.FileUploadAndDownload true "传入文件里面id即可"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
|
||||
// @Router /fileUploadAndDownload/deleteFile [post]
|
||||
func (u *FileUploadAndDownloadApi) DeleteFile(c *gin.Context) {
|
||||
var file web.FileUploadAndDownload
|
||||
_ = c.ShouldBindJSON(&file)
|
||||
if err := fileUploadAndDownloadService.DeleteFile(file); err != nil {
|
||||
global.GLOBAL_LOG.Error("删除失败!", zap.Any("err", err))
|
||||
response.FailWithMessage("删除失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// @Tags FileUploadAndDownload
|
||||
// @Summary 分页文件列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.PageInfo true "页码, 每页大小"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /fileUploadAndDownload/getFileList [post]
|
||||
func (u *FileUploadAndDownloadApi) GetFileList(c *gin.Context) {
|
||||
var pageInfo request.PageInfo
|
||||
_ = c.ShouldBindJSON(&pageInfo)
|
||||
err, list, total := fileUploadAndDownloadService.GetFileRecordInfoList(pageInfo)
|
||||
if err != nil {
|
||||
global.GLOBAL_LOG.Error("获取失败!", zap.Any("err", err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
} else {
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
"goweb-gin-demo/global"
|
||||
"goweb-gin-demo/model/common/response"
|
||||
"goweb-gin-demo/model/web"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type JwtApi struct {
|
||||
|
|
|
@ -22,6 +22,7 @@ redis:
|
|||
addr: '127.0.0.1:6379'
|
||||
password: ''
|
||||
|
||||
|
||||
# casbin configuration
|
||||
casbin:
|
||||
model-path: './resource/rbac_model.conf'
|
||||
|
@ -29,7 +30,7 @@ casbin:
|
|||
# system configuration
|
||||
system:
|
||||
env: 'develop' # Change to "develop" to skip authentication for development mode # public
|
||||
addr: 8888
|
||||
addr: 8889
|
||||
db-type: 'mysql'
|
||||
oss-type: 'local' # 控制oss选择走本期还是 七牛等其他仓 自行增加其他oss仓可以在 server/utils/upload/upload.go 中 NewOss函数配置
|
||||
use-multipoint: false
|
||||
|
@ -52,6 +53,10 @@ mysql:
|
|||
log-mode: false
|
||||
log-zap: false
|
||||
|
||||
# 本地下载文件路径
|
||||
local:
|
||||
path: '/Users/zero/Documents/uploads/file'
|
||||
|
||||
# timer task db clear table
|
||||
Timer:
|
||||
start: true
|
||||
|
|
322
docs/docs.go
322
docs/docs.go
|
@ -80,6 +80,295 @@ var doc = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/fileUploadAndDownload/breakpointContinue": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"multipart/form-data"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"FileUploadAndDownload"
|
||||
],
|
||||
"summary": "断点续传到服务器",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "file",
|
||||
"description": "an example for breakpoint resume, 断点续传示例",
|
||||
"name": "file",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{\"success\":true,\"data\":{},\"msg\":\"切片创建成功\"}",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/fileUploadAndDownload/breakpointContinueFinish": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"multipart/form-data"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"FileUploadAndDownload"
|
||||
],
|
||||
"summary": "创建文件",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "file",
|
||||
"description": "上传文件完成",
|
||||
"name": "file",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{\"success\":true,\"data\":{},\"msg\":\"file uploaded, 文件创建成功\"}",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/fileUploadAndDownload/deleteFile": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"FileUploadAndDownload"
|
||||
],
|
||||
"summary": "删除文件",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "传入文件里面id即可",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/web.FileUploadAndDownload"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{\"success\":true,\"data\":{},\"msg\":\"删除成功\"}",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/fileUploadAndDownload/download": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"FileUploadAndDownload"
|
||||
],
|
||||
"summary": "文件下载",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "待下载的文件名",
|
||||
"name": "fileName",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{\"success\":true,\"data\":{},\"msg\":\"文件下载成功\"}",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/fileUploadAndDownload/findFile": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"multipart/form-data"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"FileUploadAndDownload"
|
||||
],
|
||||
"summary": "查找文件",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "file",
|
||||
"description": "Find the file, 查找文件",
|
||||
"name": "file",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{\"success\":true,\"data\":{},\"msg\":\"查找成功\"}",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/fileUploadAndDownload/getFileList": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"FileUploadAndDownload"
|
||||
],
|
||||
"summary": "分页文件列表",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "页码, 每页大小",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.PageInfo"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/fileUploadAndDownload/removeChunk": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"multipart/form-data"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"FileUploadAndDownload"
|
||||
],
|
||||
"summary": "删除切片",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "file",
|
||||
"description": "删除缓存切片",
|
||||
"name": "file",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{\"success\":true,\"data\":{},\"msg\":\"缓存切片删除成功\"}",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/fileUploadAndDownload/upload": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"multipart/form-data"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"FileUploadAndDownload"
|
||||
],
|
||||
"summary": "上传文件示例",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "file",
|
||||
"description": "上传文件示例",
|
||||
"name": "file",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{\"success\":true,\"data\":{},\"msg\":\"上传成功\"}",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/jwt/jsonInBlacklist": {
|
||||
"post": {
|
||||
"security": [
|
||||
|
@ -1400,6 +1689,39 @@ var doc = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"web.FileUploadAndDownload": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"description": "创建时间",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"description": "主键ID",
|
||||
"type": "integer"
|
||||
},
|
||||
"key": {
|
||||
"description": "编号",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "文件名",
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"description": "文件标签",
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"description": "更新时间",
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"description": "文件地址",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"web.SysAuthority": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
@ -61,6 +61,295 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/fileUploadAndDownload/breakpointContinue": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"multipart/form-data"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"FileUploadAndDownload"
|
||||
],
|
||||
"summary": "断点续传到服务器",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "file",
|
||||
"description": "an example for breakpoint resume, 断点续传示例",
|
||||
"name": "file",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{\"success\":true,\"data\":{},\"msg\":\"切片创建成功\"}",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/fileUploadAndDownload/breakpointContinueFinish": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"multipart/form-data"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"FileUploadAndDownload"
|
||||
],
|
||||
"summary": "创建文件",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "file",
|
||||
"description": "上传文件完成",
|
||||
"name": "file",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{\"success\":true,\"data\":{},\"msg\":\"file uploaded, 文件创建成功\"}",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/fileUploadAndDownload/deleteFile": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"FileUploadAndDownload"
|
||||
],
|
||||
"summary": "删除文件",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "传入文件里面id即可",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/web.FileUploadAndDownload"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{\"success\":true,\"data\":{},\"msg\":\"删除成功\"}",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/fileUploadAndDownload/download": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"FileUploadAndDownload"
|
||||
],
|
||||
"summary": "文件下载",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "待下载的文件名",
|
||||
"name": "fileName",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{\"success\":true,\"data\":{},\"msg\":\"文件下载成功\"}",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/fileUploadAndDownload/findFile": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"multipart/form-data"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"FileUploadAndDownload"
|
||||
],
|
||||
"summary": "查找文件",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "file",
|
||||
"description": "Find the file, 查找文件",
|
||||
"name": "file",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{\"success\":true,\"data\":{},\"msg\":\"查找成功\"}",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/fileUploadAndDownload/getFileList": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"FileUploadAndDownload"
|
||||
],
|
||||
"summary": "分页文件列表",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "页码, 每页大小",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.PageInfo"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/fileUploadAndDownload/removeChunk": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"multipart/form-data"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"FileUploadAndDownload"
|
||||
],
|
||||
"summary": "删除切片",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "file",
|
||||
"description": "删除缓存切片",
|
||||
"name": "file",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{\"success\":true,\"data\":{},\"msg\":\"缓存切片删除成功\"}",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/fileUploadAndDownload/upload": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"multipart/form-data"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"FileUploadAndDownload"
|
||||
],
|
||||
"summary": "上传文件示例",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "file",
|
||||
"description": "上传文件示例",
|
||||
"name": "file",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{\"success\":true,\"data\":{},\"msg\":\"上传成功\"}",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/jwt/jsonInBlacklist": {
|
||||
"post": {
|
||||
"security": [
|
||||
|
@ -1381,6 +1670,39 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"web.FileUploadAndDownload": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"description": "创建时间",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"description": "主键ID",
|
||||
"type": "integer"
|
||||
},
|
||||
"key": {
|
||||
"description": "编号",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "文件名",
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"description": "文件标签",
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"description": "更新时间",
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"description": "文件地址",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"web.SysAuthority": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
@ -391,6 +391,30 @@ definitions:
|
|||
id:
|
||||
type: integer
|
||||
type: object
|
||||
web.FileUploadAndDownload:
|
||||
properties:
|
||||
createdAt:
|
||||
description: 创建时间
|
||||
type: string
|
||||
id:
|
||||
description: 主键ID
|
||||
type: integer
|
||||
key:
|
||||
description: 编号
|
||||
type: string
|
||||
name:
|
||||
description: 文件名
|
||||
type: string
|
||||
tag:
|
||||
description: 文件标签
|
||||
type: string
|
||||
updatedAt:
|
||||
description: 更新时间
|
||||
type: string
|
||||
url:
|
||||
description: 文件地址
|
||||
type: string
|
||||
type: object
|
||||
web.SysAuthority:
|
||||
properties:
|
||||
authorityId:
|
||||
|
@ -591,6 +615,182 @@ paths:
|
|||
summary: 用户登录
|
||||
tags:
|
||||
- Base
|
||||
/fileUploadAndDownload/breakpointContinue:
|
||||
post:
|
||||
consumes:
|
||||
- multipart/form-data
|
||||
parameters:
|
||||
- description: an example for breakpoint resume, 断点续传示例
|
||||
in: formData
|
||||
name: file
|
||||
required: true
|
||||
type: file
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: '{"success":true,"data":{},"msg":"切片创建成功"}'
|
||||
schema:
|
||||
type: string
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: 断点续传到服务器
|
||||
tags:
|
||||
- FileUploadAndDownload
|
||||
/fileUploadAndDownload/breakpointContinueFinish:
|
||||
post:
|
||||
consumes:
|
||||
- multipart/form-data
|
||||
parameters:
|
||||
- description: 上传文件完成
|
||||
in: formData
|
||||
name: file
|
||||
required: true
|
||||
type: file
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: '{"success":true,"data":{},"msg":"file uploaded, 文件创建成功"}'
|
||||
schema:
|
||||
type: string
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: 创建文件
|
||||
tags:
|
||||
- FileUploadAndDownload
|
||||
/fileUploadAndDownload/deleteFile:
|
||||
post:
|
||||
parameters:
|
||||
- description: 传入文件里面id即可
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/web.FileUploadAndDownload'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: '{"success":true,"data":{},"msg":"删除成功"}'
|
||||
schema:
|
||||
type: string
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: 删除文件
|
||||
tags:
|
||||
- FileUploadAndDownload
|
||||
/fileUploadAndDownload/download:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: 待下载的文件名
|
||||
in: query
|
||||
name: fileName
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: '{"success":true,"data":{},"msg":"文件下载成功"}'
|
||||
schema:
|
||||
type: string
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: 文件下载
|
||||
tags:
|
||||
- FileUploadAndDownload
|
||||
/fileUploadAndDownload/findFile:
|
||||
post:
|
||||
consumes:
|
||||
- multipart/form-data
|
||||
parameters:
|
||||
- description: Find the file, 查找文件
|
||||
in: formData
|
||||
name: file
|
||||
required: true
|
||||
type: file
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: '{"success":true,"data":{},"msg":"查找成功"}'
|
||||
schema:
|
||||
type: string
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: 查找文件
|
||||
tags:
|
||||
- FileUploadAndDownload
|
||||
/fileUploadAndDownload/getFileList:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: 页码, 每页大小
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/request.PageInfo'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: '{"success":true,"data":{},"msg":"获取成功"}'
|
||||
schema:
|
||||
type: string
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: 分页文件列表
|
||||
tags:
|
||||
- FileUploadAndDownload
|
||||
/fileUploadAndDownload/removeChunk:
|
||||
post:
|
||||
consumes:
|
||||
- multipart/form-data
|
||||
parameters:
|
||||
- description: 删除缓存切片
|
||||
in: formData
|
||||
name: file
|
||||
required: true
|
||||
type: file
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: '{"success":true,"data":{},"msg":"缓存切片删除成功"}'
|
||||
schema:
|
||||
type: string
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: 删除切片
|
||||
tags:
|
||||
- FileUploadAndDownload
|
||||
/fileUploadAndDownload/upload:
|
||||
post:
|
||||
consumes:
|
||||
- multipart/form-data
|
||||
parameters:
|
||||
- description: 上传文件示例
|
||||
in: formData
|
||||
name: file
|
||||
required: true
|
||||
type: file
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: '{"success":true,"data":{},"msg":"上传成功"}'
|
||||
schema:
|
||||
type: string
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: 上传文件示例
|
||||
tags:
|
||||
- FileUploadAndDownload
|
||||
/jwt/jsonInBlacklist:
|
||||
post:
|
||||
consumes:
|
||||
|
|
4
go.mod
4
go.mod
|
@ -3,6 +3,8 @@ module goweb-gin-demo
|
|||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/aliyun/aliyun-oss-go-sdk v2.1.10+incompatible
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
|
||||
github.com/casbin/casbin/v2 v2.11.0
|
||||
github.com/casbin/gorm-adapter/v3 v3.0.2
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
|
@ -16,6 +18,7 @@ require (
|
|||
github.com/lestrrat-go/strftime v1.0.5 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mojocn/base64Captcha v1.3.1
|
||||
github.com/qiniu/api.v7/v7 v7.8.2
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/satori/go.uuid v1.2.0
|
||||
github.com/shirou/gopsutil v3.20.11+incompatible
|
||||
|
@ -24,6 +27,7 @@ require (
|
|||
github.com/stretchr/testify v1.7.0
|
||||
github.com/swaggo/gin-swagger v1.3.2
|
||||
github.com/swaggo/swag v1.7.4
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.31
|
||||
go.uber.org/zap v1.16.0
|
||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309 // indirect
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
|
|
20
go.sum
20
go.sum
|
@ -24,14 +24,19 @@ github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tN
|
|||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v2.1.10+incompatible h1:D3gwOr9qUUmyyBRDbpnATqu+EkqqmigFd3Od6xO1QUU=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v2.1.10+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA=
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
|
@ -166,14 +171,20 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gookit/color v1.3.6 h1:Rgbazd4JO5AgSTVGS3o0nvaSdwdrS8bzvIXwtK6OiMk=
|
||||
github.com/gookit/color v1.3.6/go.mod h1:R3ogXq2B9rTbXoSHJ1HyUVAZ3poOJHpd9nQmyGZsfvQ=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
|
@ -332,6 +343,8 @@ github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9
|
|||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mojocn/base64Captcha v1.3.1 h1:2Wbkt8Oc8qjmNJ5GyOfSo4tgVQPsbKMftqASnq8GlT0=
|
||||
github.com/mojocn/base64Captcha v1.3.1/go.mod h1:wAQCKEc5bDujxKRmbT6/vTnTt5CjStQ8bRfPWUuz/iY=
|
||||
github.com/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSrwhe88TQQ=
|
||||
github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
|
@ -366,6 +379,8 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
|
|||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/qiniu/api.v7/v7 v7.8.2 h1:f08kI0MmsJNzK4sUS8bG3HDH67ktwd/ji23Gkiy2ra4=
|
||||
github.com/qiniu/api.v7/v7 v7.8.2/go.mod h1:FPsIqxh1Ym3X01sANE5ZwXfLZSWoCUp5+jNI8cLo3l0=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
|
@ -424,6 +439,10 @@ github.com/swaggo/gin-swagger v1.3.2/go.mod h1:8GN8KIlwgjawtEvE+B8sx3q9SPJuX/ZPx
|
|||
github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+tv8Y=
|
||||
github.com/swaggo/swag v1.7.4 h1:up+ixy8yOqJKiFcuhMgkuYuF4xnevuhnFAXXF8OSfNg=
|
||||
github.com/swaggo/swag v1.7.4/go.mod h1:zD8h6h4SPv7t3l+4BKdRquqW1ASWjKZgT6Qv9z3kNqI=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.194/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.194/go.mod h1:yrBKWhChnDqNz1xuXdSbWXG56XawEq0G5j1lg4VwBD4=
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.31 h1:NujkkOKMJ3IFs1+trCwXOKRCIPQ8qI5Lxul9JkhTg6M=
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.31/go.mod h1:4E4+bQ2gBVJcgEC9Cufwylio4mXOct2iu05WjgEBx1o=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
|
@ -578,6 +597,7 @@ golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
|||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
|
BIN
goweb-gin-demo
BIN
goweb-gin-demo
Binary file not shown.
|
@ -38,6 +38,8 @@ func Routers() *gin.Engine {
|
|||
RouterGroup.InitJwtRouter(PrivateGroup)
|
||||
RouterGroup.InitUserRouter(PrivateGroup)
|
||||
RouterGroup.InitMenuRouter(PrivateGroup)
|
||||
RouterGroup.InitSystemRouter(PrivateGroup)
|
||||
RouterGroup.InitFileUploadAndDownloadRouter(PrivateGroup)
|
||||
}
|
||||
|
||||
global.GLOBAL_LOG.Info("router register success")
|
||||
|
|
|
@ -4,3 +4,71 @@
|
|||
[goweb-demo]2021/11/02 - 11:30:42.979 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:43 router register success
|
||||
[goweb-demo]2021/11/02 - 11:30:42.982 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8888"}
|
||||
[goweb-demo]2021/11/02 - 11:30:44.819 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:38 accept tcp [::]:8888: use of closed network connection
|
||||
[goweb-demo]2021/11/02 - 14:32:20.344 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:43 router register success
|
||||
[goweb-demo]2021/11/02 - 14:32:20.346 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8888"}
|
||||
[goweb-demo]2021/11/02 - 14:32:20.347 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:38 net.Listen error: listen tcp :8888: bind: address already in use
|
||||
[goweb-demo]2021/11/02 - 14:32:42.358 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:43 router register success
|
||||
[goweb-demo]2021/11/02 - 14:32:42.359 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8888"}
|
||||
[goweb-demo]2021/11/02 - 14:59:57.739 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 14:59:57.742 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 15:00:08.777 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:38 accept tcp [::]:8889: use of closed network connection
|
||||
[goweb-demo]2021/11/02 - 15:00:15.664 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 15:00:15.666 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 15:07:51.456 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:38 accept tcp [::]:8889: use of closed network connection
|
||||
[goweb-demo]2021/11/02 - 15:08:07.925 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 15:08:07.927 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8888"}
|
||||
[goweb-demo]2021/11/02 - 15:17:02.625 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 15:17:02.628 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8888"}
|
||||
[goweb-demo]2021/11/02 - 15:34:46.466 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/api/web/user.go:36 登陆失败! 用户名不存在或者密码错误! {"err": "invalid connection"}
|
||||
[goweb-demo]2021/11/02 - 15:37:39.579 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 15:37:39.582 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 15:54:23.350 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:38 accept tcp [::]:8889: use of closed network connection
|
||||
[goweb-demo]2021/11/02 - 15:54:32.834 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 15:54:32.836 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 16:06:12.308 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 16:06:12.309 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 16:09:47.266 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:38 accept tcp [::]:8889: use of closed network connection
|
||||
[goweb-demo]2021/11/02 - 16:09:54.752 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 16:09:54.755 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 16:20:39.040 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/utils/upload/local.go:39 function os.MkdirAll() Filed {"err": "mkdir : no such file or directory"}
|
||||
[goweb-demo]2021/11/02 - 16:21:07.385 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/utils/upload/local.go:39 function os.MkdirAll() Filed {"err": "mkdir : no such file or directory"}
|
||||
[goweb-demo]2021/11/02 - 16:26:23.159 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:38 accept tcp [::]:8889: use of closed network connection
|
||||
[goweb-demo]2021/11/02 - 16:26:31.302 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 16:26:31.306 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 16:35:48.848 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/utils/upload/local.go:39 function os.MkdirAll() Filed {"err": "mkdir : no such file or directory"}
|
||||
[goweb-demo]2021/11/02 - 16:37:09.761 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 16:37:09.764 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 16:37:17.352 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/api/web/file_upload_download.go:35 修改数据库链接失败! {"err": "Error 1146: Table 'weekly_report.exa_file_upload_and_downloads' doesn't exist"}
|
||||
[goweb-demo]2021/11/02 - 17:03:38.349 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 17:03:38.353 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 17:14:21.779 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 17:14:21.782 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 17:29:03.543 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:38 accept tcp [::]:8889: use of closed network connection
|
||||
[goweb-demo]2021/11/02 - 17:29:11.545 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 17:29:11.552 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 17:56:09.792 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:38 accept tcp [::]:8889: use of closed network connection
|
||||
[goweb-demo]2021/11/02 - 17:56:20.437 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 17:56:20.440 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 19:52:46.120 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 19:52:46.124 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 19:53:04.183 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:38 accept tcp [::]:8889: use of closed network connection
|
||||
[goweb-demo]2021/11/02 - 19:53:13.557 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 19:53:13.559 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 19:54:22.978 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:38 accept tcp [::]:8889: use of closed network connection
|
||||
[goweb-demo]2021/11/02 - 19:54:31.396 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 19:54:31.399 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 19:56:09.819 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 19:56:09.822 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 19:57:48.713 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 19:57:48.717 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 19:58:18.069 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 19:58:18.070 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 20:01:23.356 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/api/web/file_upload_download.go:58 文件未找到! {"err": "Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key = ? AND `file_upload_and_downloads`.`deleted_at` IS NULL ORDER BY `file_uplo' at line 1"}
|
||||
[goweb-demo]2021/11/02 - 20:01:38.751 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/api/web/file_upload_download.go:58 文件未找到! {"err": "Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key = ? AND `file_upload_and_downloads`.`deleted_at` IS NULL ORDER BY `file_uplo' at line 1"}
|
||||
[goweb-demo]2021/11/02 - 20:04:10.155 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 20:04:10.159 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 20:07:53.705 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 20:07:53.709 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 20:09:04.558 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/initialize/router.go:45 router register success
|
||||
[goweb-demo]2021/11/02 - 20:09:04.562 [34minfo[0m /Users/zero/work/mygithub/goweb-gin-demo/core/server.go:31 server run success on {"address": ":8889"}
|
||||
[goweb-demo]2021/11/02 - 20:09:44.609 [31merror[0m /Users/zero/work/mygithub/goweb-gin-demo/api/web/file_upload_download.go:59 文件未找到! {"err": "record not found"}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"goweb-gin-demo/global"
|
||||
)
|
||||
|
||||
// file struct, 文件结构体
|
||||
type File struct {
|
||||
global.GLOBAL_MODEL
|
||||
FileName string
|
||||
FileMd5 string
|
||||
FilePath string
|
||||
ExaFileChunk []FileChunk
|
||||
ChunkTotal int
|
||||
IsFinish bool
|
||||
}
|
||||
|
||||
// file chunk struct, 切片结构体
|
||||
type FileChunk struct {
|
||||
global.GLOBAL_MODEL
|
||||
ExaFileID uint
|
||||
FileChunkNumber int
|
||||
FileChunkPath string
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"goweb-gin-demo/global"
|
||||
)
|
||||
|
||||
type FileUploadAndDownload struct {
|
||||
global.GLOBAL_MODEL
|
||||
Name string `json:"name" gorm:"comment:文件名"` // 文件名
|
||||
Url string `json:"url" gorm:"comment:文件地址"` // 文件地址
|
||||
Tag string `json:"tag" gorm:"comment:文件标签"` // 文件标签
|
||||
Key string `json:"key" gorm:"comment:编号"` // 编号
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package response
|
||||
|
||||
import "goweb-gin-demo/model/web"
|
||||
|
||||
type FilePathResponse struct {
|
||||
FilePath string `json:"filePath"`
|
||||
}
|
||||
|
||||
type FileResponse struct {
|
||||
File web.File `json:"file"`
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package response
|
||||
|
||||
import "goweb-gin-demo/model/web"
|
||||
|
||||
type ExaFileResponse struct {
|
||||
File web.FileUploadAndDownload `json:"file"`
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 292 KiB |
|
@ -7,6 +7,8 @@ type RouterGroup struct {
|
|||
web.JwtRouter
|
||||
web.UserRouter
|
||||
web.MenuRouter
|
||||
web.SysRouter
|
||||
web.FileUploadAndDownloadRouter
|
||||
}
|
||||
|
||||
var RouterGroupApp = new(RouterGroup)
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"goweb-gin-demo/api"
|
||||
)
|
||||
|
||||
type FileUploadAndDownloadRouter struct {
|
||||
}
|
||||
|
||||
func (e *FileUploadAndDownloadRouter) InitFileUploadAndDownloadRouter(Router *gin.RouterGroup) {
|
||||
fileUploadAndDownloadRouter := Router.Group("fileUploadAndDownload")
|
||||
var fileUploadAndDownloadApi = api.ApiGroupApp.ApiGroup.FileUploadAndDownloadApi
|
||||
{
|
||||
fileUploadAndDownloadRouter.POST("upload", fileUploadAndDownloadApi.UploadFile) // 上传文件
|
||||
fileUploadAndDownloadRouter.GET("download", fileUploadAndDownloadApi.DownloadFile) // 文件下载
|
||||
fileUploadAndDownloadRouter.POST("getFileList", fileUploadAndDownloadApi.GetFileList) // 获取上传文件列表
|
||||
fileUploadAndDownloadRouter.POST("deleteFile", fileUploadAndDownloadApi.DeleteFile) // 删除指定文件
|
||||
fileUploadAndDownloadRouter.POST("breakpointContinue", fileUploadAndDownloadApi.BreakpointContinue) // 断点续传
|
||||
fileUploadAndDownloadRouter.GET("findFile", fileUploadAndDownloadApi.FindFile) // 查询当前文件成功的切片
|
||||
fileUploadAndDownloadRouter.POST("breakpointContinueFinish", fileUploadAndDownloadApi.BreakpointContinueFinish) // 查询当前文件成功的切片
|
||||
fileUploadAndDownloadRouter.POST("removeChunk", fileUploadAndDownloadApi.RemoveChunk) // 查询当前文件成功的切片
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ package web
|
|||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
v1 "goweb-gin-demo/api"
|
||||
"goweb-gin-demo/api"
|
||||
)
|
||||
|
||||
type JwtRouter struct {
|
||||
|
@ -10,7 +10,7 @@ type JwtRouter struct {
|
|||
|
||||
func (s *JwtRouter) InitJwtRouter(Router *gin.RouterGroup) {
|
||||
jwtRouter := Router.Group("jwt")
|
||||
var jwtApi = v1.ApiGroupApp.ApiGroup.JwtApi
|
||||
var jwtApi = api.ApiGroupApp.ApiGroup.JwtApi
|
||||
{
|
||||
jwtRouter.POST("jsonInBlacklist", jwtApi.JsonInBlacklist) // jwt加入黑名单
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package web
|
|||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
v1 "goweb-gin-demo/api"
|
||||
"goweb-gin-demo/api"
|
||||
"goweb-gin-demo/middleware"
|
||||
)
|
||||
|
||||
|
@ -12,7 +12,7 @@ type MenuRouter struct {
|
|||
func (s *MenuRouter) InitMenuRouter(Router *gin.RouterGroup) (R gin.IRoutes) {
|
||||
menuRouter := Router.Group("menu").Use(middleware.OperationRecord())
|
||||
menuRouterWithoutRecord := Router.Group("menu")
|
||||
var authorityMenuApi = v1.ApiGroupApp.ApiGroup.AuthorityMenuApi
|
||||
var authorityMenuApi = api.ApiGroupApp.ApiGroup.AuthorityMenuApi
|
||||
{
|
||||
menuRouter.POST("addBaseMenu", authorityMenuApi.AddBaseMenu) // 新增菜单
|
||||
menuRouter.POST("addMenuAuthority", authorityMenuApi.AddMenuAuthority) // 增加menu和角色关联关系
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"goweb-gin-demo/api"
|
||||
"goweb-gin-demo/middleware"
|
||||
)
|
||||
|
||||
type SysRouter struct {
|
||||
}
|
||||
|
||||
func (s *SysRouter) InitSystemRouter(Router *gin.RouterGroup) {
|
||||
sysRouter := Router.Group("system").Use(middleware.OperationRecord())
|
||||
var systemApi = api.ApiGroupApp.ApiGroup.SystemApi
|
||||
{
|
||||
sysRouter.POST("getSystemConfig", systemApi.GetSystemConfig) // 获取配置文件内容
|
||||
sysRouter.POST("setSystemConfig", systemApi.SetSystemConfig) // 设置配置文件内容
|
||||
sysRouter.POST("getServerInfo", systemApi.GetServerInfo) // 获取服务器信息
|
||||
sysRouter.POST("reloadSystem", systemApi.ReloadSystem) // 重启服务
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ package web
|
|||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
v1 "goweb-gin-demo/api"
|
||||
"goweb-gin-demo/api"
|
||||
"goweb-gin-demo/middleware"
|
||||
)
|
||||
|
||||
|
@ -12,7 +12,7 @@ type UserRouter struct {
|
|||
func (s *UserRouter) InitUserRouter(Router *gin.RouterGroup) {
|
||||
userRouter := Router.Group("user").Use(middleware.OperationRecord())
|
||||
userRouterWithoutRecord := Router.Group("user")
|
||||
var baseApi = v1.ApiGroupApp.ApiGroup.BaseApi
|
||||
var baseApi = api.ApiGroupApp.ApiGroup.BaseApi
|
||||
{
|
||||
userRouter.POST("register", baseApi.Register) // 用户注册账号
|
||||
userRouter.POST("changePassword", baseApi.ChangePassword) // 用户修改密码
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"goweb-gin-demo/global"
|
||||
"goweb-gin-demo/model/web"
|
||||
)
|
||||
|
||||
type FileUploadAndDownloadService struct {
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: FindOrCreateFile
|
||||
//@description: 上传文件时检测当前文件属性,如果没有文件则创建,有则返回文件的当前切片
|
||||
//@param: fileMd5 string, fileName string, chunkTotal int
|
||||
//@return: err error, file model.File
|
||||
|
||||
func (e *FileUploadAndDownloadService) FindOrCreateFile(fileMd5 string, fileName string, chunkTotal int) (err error, file web.File) {
|
||||
var cfile web.File
|
||||
cfile.FileMd5 = fileMd5
|
||||
cfile.FileName = fileName
|
||||
cfile.ChunkTotal = chunkTotal
|
||||
|
||||
if errors.Is(global.GLOBAL_DB.Where("file_md5 = ? AND is_finish = ?", fileMd5, true).First(&file).Error, gorm.ErrRecordNotFound) {
|
||||
err = global.GLOBAL_DB.Where("file_md5 = ? AND file_name = ?", fileMd5, fileName).Preload("FileChunk").FirstOrCreate(&file, cfile).Error
|
||||
return err, file
|
||||
}
|
||||
cfile.IsFinish = true
|
||||
cfile.FilePath = file.FilePath
|
||||
err = global.GLOBAL_DB.Create(&cfile).Error
|
||||
return err, cfile
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: CreateFileChunk
|
||||
//@description: 创建文件切片记录
|
||||
//@param: id uint, fileChunkPath string, fileChunkNumber int
|
||||
//@return: error
|
||||
|
||||
func (e *FileUploadAndDownloadService) CreateFileChunk(id uint, fileChunkPath string, fileChunkNumber int) error {
|
||||
var chunk web.FileChunk
|
||||
chunk.FileChunkPath = fileChunkPath
|
||||
chunk.ExaFileID = id
|
||||
chunk.FileChunkNumber = fileChunkNumber
|
||||
err := global.GLOBAL_DB.Create(&chunk).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: DeleteFileChunk
|
||||
//@description: 删除文件切片记录
|
||||
//@param: fileMd5 string, fileName string, filePath string
|
||||
//@return: error
|
||||
|
||||
func (e *FileUploadAndDownloadService) DeleteFileChunk(fileMd5 string, fileName string, filePath string) error {
|
||||
var chunks []web.FileChunk
|
||||
var file web.File
|
||||
err := global.GLOBAL_DB.Where("file_md5 = ? AND file_name = ?", fileMd5, fileName).First(&file).Update("IsFinish", true).Update("file_path", filePath).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = global.GLOBAL_DB.Where("exa_file_id = ?", file.ID).Delete(&chunks).Unscoped().Error
|
||||
return err
|
||||
}
|
|
@ -8,6 +8,7 @@ type ServiceGroup struct {
|
|||
MenuService
|
||||
BaseMenuService
|
||||
SystemConfigService
|
||||
FileUploadAndDownloadService
|
||||
}
|
||||
|
||||
var ServiceGroupApp = new(ServiceGroup)
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"mime/multipart"
|
||||
"strings"
|
||||
|
||||
"goweb-gin-demo/global"
|
||||
"goweb-gin-demo/model/common/request"
|
||||
"goweb-gin-demo/model/web"
|
||||
"goweb-gin-demo/utils/upload"
|
||||
)
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: Upload
|
||||
//@description: 创建文件上传记录
|
||||
//@param: file model.FileUploadAndDownload
|
||||
//@return: error
|
||||
|
||||
func (e *FileUploadAndDownloadService) Upload(file web.FileUploadAndDownload) error {
|
||||
return global.GLOBAL_DB.Create(&file).Error
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: FindFile
|
||||
//@description: 查找文件
|
||||
//@param: id uint
|
||||
//@return: error, model.FileUploadAndDownload
|
||||
|
||||
func (e *FileUploadAndDownloadService) FindFile(key string) (error, web.FileUploadAndDownload) {
|
||||
var file web.FileUploadAndDownload
|
||||
err := global.GLOBAL_DB.Where("`key` = ?", key).First(&file).Error
|
||||
return err, file
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: DeleteFile
|
||||
//@description: 删除文件记录
|
||||
//@param: file model.FileUploadAndDownload
|
||||
//@return: err error
|
||||
|
||||
func (e *FileUploadAndDownloadService) DeleteFile(file web.FileUploadAndDownload) (err error) {
|
||||
var fileFromDb web.FileUploadAndDownload
|
||||
err, fileFromDb = e.FindFile(file.Key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
oss := upload.NewOss()
|
||||
if err = oss.DeleteFile(fileFromDb.Key); err != nil {
|
||||
return errors.New("文件删除失败")
|
||||
}
|
||||
err = global.GLOBAL_DB.Where("id = ?", file.ID).Unscoped().Delete(&file).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetFileRecordInfoList
|
||||
//@description: 分页获取数据
|
||||
//@param: info request.PageInfo
|
||||
//@return: err error, list interface{}, total int64
|
||||
|
||||
func (e *FileUploadAndDownloadService) GetFileRecordInfoList(info request.PageInfo) (err error, list interface{}, total int64) {
|
||||
limit := info.PageSize
|
||||
offset := info.PageSize * (info.Page - 1)
|
||||
db := global.GLOBAL_DB.Model(&web.FileUploadAndDownload{})
|
||||
var fileLists []web.FileUploadAndDownload
|
||||
err = db.Count(&total).Error
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = db.Limit(limit).Offset(offset).Order("updated_at desc").Find(&fileLists).Error
|
||||
return err, fileLists, total
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: UploadFile
|
||||
//@description: 根据配置文件判断是文件上传到本地或者七牛云
|
||||
//@param: header *multipart.FileHeader, noSave string
|
||||
//@return: err error, file model.FileUploadAndDownload
|
||||
|
||||
func (e *FileUploadAndDownloadService) UploadFile(header *multipart.FileHeader, noSave string) (err error, file web.FileUploadAndDownload) {
|
||||
oss := upload.NewOss()
|
||||
filePath, key, uploadErr := oss.UploadFile(header)
|
||||
if uploadErr != nil {
|
||||
panic(err)
|
||||
}
|
||||
if noSave == "0" {
|
||||
s := strings.Split(header.Filename, ".")
|
||||
f := web.FileUploadAndDownload{
|
||||
Url: filePath,
|
||||
Name: header.Filename,
|
||||
Tag: s[len(s)-1],
|
||||
Key: key,
|
||||
}
|
||||
return e.Upload(f), f
|
||||
}
|
||||
return
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// 前端传来文件片与当前片为什么文件的第几片
|
||||
// 后端拿到以后比较次分片是否上传 或者是否为不完全片
|
||||
// 前端发送每片多大
|
||||
// 前端告知是否为最后一片且是否完成
|
||||
|
||||
const breakpointDir = "./breakpointDir/"
|
||||
const finishDir = "./fileDir/"
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: BreakPointContinue
|
||||
//@description: 断点续传
|
||||
//@param: content []byte, fileName string, contentNumber int, contentTotal int, fileMd5 string
|
||||
//@return: error, string
|
||||
|
||||
func BreakPointContinue(content []byte, fileName string, contentNumber int, contentTotal int, fileMd5 string) (error, string) {
|
||||
path := breakpointDir + fileMd5 + "/"
|
||||
err := os.MkdirAll(path, os.ModePerm)
|
||||
if err != nil {
|
||||
return err, path
|
||||
}
|
||||
err, pathc := makeFileContent(content, fileName, path, contentNumber)
|
||||
return err, pathc
|
||||
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: CheckMd5
|
||||
//@description: 检查Md5
|
||||
//@param: content []byte, chunkMd5 string
|
||||
//@return: CanUpload bool
|
||||
|
||||
func CheckMd5(content []byte, chunkMd5 string) (CanUpload bool) {
|
||||
fileMd5 := MD5V(content)
|
||||
if fileMd5 == chunkMd5 {
|
||||
return true // 可以继续上传
|
||||
} else {
|
||||
return false // 切片不完整,废弃
|
||||
}
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: makeFileContent
|
||||
//@description: 创建切片内容
|
||||
//@param: content []byte, fileName string, FileDir string, contentNumber int
|
||||
//@return: error, string
|
||||
|
||||
func makeFileContent(content []byte, fileName string, FileDir string, contentNumber int) (error, string) {
|
||||
path := FileDir + fileName + "_" + strconv.Itoa(contentNumber)
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
return err, path
|
||||
} else {
|
||||
_, err = f.Write(content)
|
||||
if err != nil {
|
||||
return err, path
|
||||
}
|
||||
}
|
||||
defer f.Close()
|
||||
return nil, path
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: makeFileContent
|
||||
//@description: 创建切片文件
|
||||
//@param: fileName string, FileMd5 string
|
||||
//@return: error, string
|
||||
|
||||
func MakeFile(fileName string, FileMd5 string) (error, string) {
|
||||
rd, err := ioutil.ReadDir(breakpointDir + FileMd5)
|
||||
if err != nil {
|
||||
return err, finishDir + fileName
|
||||
}
|
||||
_ = os.MkdirAll(finishDir, os.ModePerm)
|
||||
fd, err := os.OpenFile(finishDir+fileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
|
||||
if err != nil {
|
||||
return err, finishDir + fileName
|
||||
}
|
||||
defer fd.Close()
|
||||
for k := range rd {
|
||||
content, _ := ioutil.ReadFile(breakpointDir + FileMd5 + "/" + fileName + "_" + strconv.Itoa(k))
|
||||
_, err = fd.Write(content)
|
||||
if err != nil {
|
||||
_ = os.Remove(finishDir + fileName)
|
||||
return err, finishDir + fileName
|
||||
}
|
||||
}
|
||||
return nil, finishDir + fileName
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: RemoveChunk
|
||||
//@description: 移除切片
|
||||
//@param: FileMd5 string
|
||||
//@return: error
|
||||
|
||||
func RemoveChunk(FileMd5 string) error {
|
||||
err := os.RemoveAll(breakpointDir + FileMd5)
|
||||
return err
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package upload
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"mime/multipart"
|
||||
"time"
|
||||
|
||||
"github.com/aliyun/aliyun-oss-go-sdk/oss"
|
||||
"goweb-gin-demo/global"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type AliyunOSS struct{}
|
||||
|
||||
func (*AliyunOSS) UploadFile(file *multipart.FileHeader) (string, string, error) {
|
||||
bucket, err := NewBucket()
|
||||
if err != nil {
|
||||
global.GLOBAL_LOG.Error("function AliyunOSS.NewBucket() Failed", zap.Any("err", err.Error()))
|
||||
return "", "", errors.New("function AliyunOSS.NewBucket() Failed, err:" + err.Error())
|
||||
}
|
||||
|
||||
// 读取本地文件。
|
||||
f, openError := file.Open()
|
||||
if openError != nil {
|
||||
global.GLOBAL_LOG.Error("function file.Open() Failed", zap.Any("err", openError.Error()))
|
||||
return "", "", errors.New("function file.Open() Failed, err:" + openError.Error())
|
||||
}
|
||||
defer f.Close() // 创建文件 defer 关闭
|
||||
// 上传阿里云路径 文件名格式 自己可以改 建议保证唯一性
|
||||
//yunFileTmpPath := filepath.Join("uploads", time.Now().Format("2006-01-02")) + "/" + file.Filename
|
||||
yunFileTmpPath := global.GLOBAL_CONFIG.AliyunOSS.BasePath + "/" + "uploads" + "/" + time.Now().Format("2006-01-02") + "/" + file.Filename
|
||||
|
||||
// 上传文件流。
|
||||
err = bucket.PutObject(yunFileTmpPath, f)
|
||||
if err != nil {
|
||||
global.GLOBAL_LOG.Error("function formUploader.Put() Failed", zap.Any("err", err.Error()))
|
||||
return "", "", errors.New("function formUploader.Put() Failed, err:" + err.Error())
|
||||
}
|
||||
|
||||
return global.GLOBAL_CONFIG.AliyunOSS.BucketUrl + "/" + yunFileTmpPath, yunFileTmpPath, nil
|
||||
}
|
||||
|
||||
func (*AliyunOSS) DeleteFile(key string) error {
|
||||
bucket, err := NewBucket()
|
||||
if err != nil {
|
||||
global.GLOBAL_LOG.Error("function AliyunOSS.NewBucket() Failed", zap.Any("err", err.Error()))
|
||||
return errors.New("function AliyunOSS.NewBucket() Failed, err:" + err.Error())
|
||||
}
|
||||
|
||||
// 删除单个文件。objectName表示删除OSS文件时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。
|
||||
// 如需删除文件夹,请将objectName设置为对应的文件夹名称。如果文件夹非空,则需要将文件夹下的所有object删除后才能删除该文件夹。
|
||||
err = bucket.DeleteObject(key)
|
||||
if err != nil {
|
||||
global.GLOBAL_LOG.Error("function bucketManager.Delete() Filed", zap.Any("err", err.Error()))
|
||||
return errors.New("function bucketManager.Delete() Filed, err:" + err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewBucket() (*oss.Bucket, error) {
|
||||
// 创建OSSClient实例。
|
||||
client, err := oss.New(global.GLOBAL_CONFIG.AliyunOSS.Endpoint, global.GLOBAL_CONFIG.AliyunOSS.AccessKeyId, global.GLOBAL_CONFIG.AliyunOSS.AccessKeySecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 获取存储空间。
|
||||
bucket, err := client.Bucket(global.GLOBAL_CONFIG.AliyunOSS.BucketName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bucket, nil
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package upload
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"goweb-gin-demo/global"
|
||||
"goweb-gin-demo/utils"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type Local struct{}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@author: [ccfish86](https://github.com/ccfish86)
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@object: *Local
|
||||
//@function: UploadFile
|
||||
//@description: 上传文件
|
||||
//@param: file *multipart.FileHeader
|
||||
//@return: string, string, error
|
||||
|
||||
func (*Local) UploadFile(file *multipart.FileHeader) (string, string, error) {
|
||||
// 读取文件后缀
|
||||
ext := path.Ext(file.Filename)
|
||||
// 读取文件名并加密
|
||||
name := strings.TrimSuffix(file.Filename, ext)
|
||||
name = utils.MD5V([]byte(name))
|
||||
// 拼接新文件名
|
||||
filename := name + "_" + time.Now().Format("20060102150405") + ext
|
||||
// 尝试创建此路径
|
||||
mkdirErr := os.MkdirAll(global.GLOBAL_CONFIG.Local.Path, os.ModePerm)
|
||||
if mkdirErr != nil {
|
||||
global.GLOBAL_LOG.Error("function os.MkdirAll() Filed", zap.Any("err", mkdirErr.Error()))
|
||||
return "", "", errors.New("function os.MkdirAll() Filed, err:" + mkdirErr.Error())
|
||||
}
|
||||
// 拼接路径和文件名
|
||||
p := global.GLOBAL_CONFIG.Local.Path + "/" + filename
|
||||
|
||||
f, openError := file.Open() // 读取文件
|
||||
if openError != nil {
|
||||
global.GLOBAL_LOG.Error("function file.Open() Filed", zap.Any("err", openError.Error()))
|
||||
return "", "", errors.New("function file.Open() Filed, err:" + openError.Error())
|
||||
}
|
||||
defer f.Close() // 创建文件 defer 关闭
|
||||
|
||||
out, createErr := os.Create(p)
|
||||
if createErr != nil {
|
||||
global.GLOBAL_LOG.Error("function os.Create() Filed", zap.Any("err", createErr.Error()))
|
||||
|
||||
return "", "", errors.New("function os.Create() Filed, err:" + createErr.Error())
|
||||
}
|
||||
defer out.Close() // 创建文件 defer 关闭
|
||||
|
||||
_, copyErr := io.Copy(out, f) // 传输(拷贝)文件
|
||||
if copyErr != nil {
|
||||
global.GLOBAL_LOG.Error("function io.Copy() Filed", zap.Any("err", copyErr.Error()))
|
||||
return "", "", errors.New("function io.Copy() Filed, err:" + copyErr.Error())
|
||||
}
|
||||
return p, filename, nil
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@author: [ccfish86](https://github.com/ccfish86)
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@object: *Local
|
||||
//@function: DeleteFile
|
||||
//@description: 删除文件
|
||||
//@param: key string
|
||||
//@return: error
|
||||
|
||||
func (*Local) DeleteFile(key string) error {
|
||||
p := global.GLOBAL_CONFIG.Local.Path + "/" + key
|
||||
if strings.Contains(p, global.GLOBAL_CONFIG.Local.Path) {
|
||||
if err := os.Remove(p); err != nil {
|
||||
return errors.New("本地文件删除失败, err:" + err.Error())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package upload
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"time"
|
||||
|
||||
"goweb-gin-demo/global"
|
||||
"github.com/qiniu/api.v7/v7/auth/qbox"
|
||||
"github.com/qiniu/api.v7/v7/storage"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type Qiniu struct{}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@author: [ccfish86](https://github.com/ccfish86)
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@object: *Qiniu
|
||||
//@function: UploadFile
|
||||
//@description: 上传文件
|
||||
//@param: file *multipart.FileHeader
|
||||
//@return: string, string, error
|
||||
|
||||
func (*Qiniu) UploadFile(file *multipart.FileHeader) (string, string, error) {
|
||||
putPolicy := storage.PutPolicy{Scope: global.GLOBAL_CONFIG.Qiniu.Bucket}
|
||||
mac := qbox.NewMac(global.GLOBAL_CONFIG.Qiniu.AccessKey, global.GLOBAL_CONFIG.Qiniu.SecretKey)
|
||||
upToken := putPolicy.UploadToken(mac)
|
||||
cfg := qiniuConfig()
|
||||
formUploader := storage.NewFormUploader(cfg)
|
||||
ret := storage.PutRet{}
|
||||
putExtra := storage.PutExtra{Params: map[string]string{"x:name": "github logo"}}
|
||||
|
||||
f, openError := file.Open()
|
||||
if openError != nil {
|
||||
global.GLOBAL_LOG.Error("function file.Open() Filed", zap.Any("err", openError.Error()))
|
||||
|
||||
return "", "", errors.New("function file.Open() Filed, err:" + openError.Error())
|
||||
}
|
||||
defer f.Close() // 创建文件 defer 关闭
|
||||
fileKey := fmt.Sprintf("%d%s", time.Now().Unix(), file.Filename) // 文件名格式 自己可以改 建议保证唯一性
|
||||
putErr := formUploader.Put(context.Background(), &ret, upToken, fileKey, f, file.Size, &putExtra)
|
||||
if putErr != nil {
|
||||
global.GLOBAL_LOG.Error("function formUploader.Put() Filed", zap.Any("err", putErr.Error()))
|
||||
return "", "", errors.New("function formUploader.Put() Filed, err:" + putErr.Error())
|
||||
}
|
||||
return global.GLOBAL_CONFIG.Qiniu.ImgPath + "/" + ret.Key, ret.Key, nil
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@author: [ccfish86](https://github.com/ccfish86)
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@object: *Qiniu
|
||||
//@function: DeleteFile
|
||||
//@description: 删除文件
|
||||
//@param: key string
|
||||
//@return: error
|
||||
|
||||
func (*Qiniu) DeleteFile(key string) error {
|
||||
mac := qbox.NewMac(global.GLOBAL_CONFIG.Qiniu.AccessKey, global.GLOBAL_CONFIG.Qiniu.SecretKey)
|
||||
cfg := qiniuConfig()
|
||||
bucketManager := storage.NewBucketManager(mac, cfg)
|
||||
if err := bucketManager.Delete(global.GLOBAL_CONFIG.Qiniu.Bucket, key); err != nil {
|
||||
global.GLOBAL_LOG.Error("function bucketManager.Delete() Filed", zap.Any("err", err.Error()))
|
||||
return errors.New("function bucketManager.Delete() Filed, err:" + err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@object: *Qiniu
|
||||
//@function: qiniuConfig
|
||||
//@description: 根据配置文件进行返回七牛云的配置
|
||||
//@return: *storage.Config
|
||||
|
||||
func qiniuConfig() *storage.Config {
|
||||
cfg := storage.Config{
|
||||
UseHTTPS: global.GLOBAL_CONFIG.Qiniu.UseHTTPS,
|
||||
UseCdnDomains: global.GLOBAL_CONFIG.Qiniu.UseCdnDomains,
|
||||
}
|
||||
switch global.GLOBAL_CONFIG.Qiniu.Zone { // 根据配置文件进行初始化空间对应的机房
|
||||
case "ZoneHuadong":
|
||||
cfg.Zone = &storage.ZoneHuadong
|
||||
case "ZoneHuabei":
|
||||
cfg.Zone = &storage.ZoneHuabei
|
||||
case "ZoneHuanan":
|
||||
cfg.Zone = &storage.ZoneHuanan
|
||||
case "ZoneBeimei":
|
||||
cfg.Zone = &storage.ZoneBeimei
|
||||
case "ZoneXinjiapo":
|
||||
cfg.Zone = &storage.ZoneXinjiapo
|
||||
}
|
||||
return &cfg
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package upload
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/tencentyun/cos-go-sdk-v5"
|
||||
"go.uber.org/zap"
|
||||
"goweb-gin-demo/global"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
type TencentCOS struct{}
|
||||
|
||||
// UploadFile upload file to COS
|
||||
func (*TencentCOS) UploadFile(file *multipart.FileHeader) (string, string, error) {
|
||||
client := NewClient()
|
||||
f, openError := file.Open()
|
||||
if openError != nil {
|
||||
global.GLOBAL_LOG.Error("function file.Open() Filed", zap.Any("err", openError.Error()))
|
||||
return "", "", errors.New("function file.Open() Filed, err:" + openError.Error())
|
||||
}
|
||||
defer f.Close() // 创建文件 defer 关闭
|
||||
fileKey := fmt.Sprintf("%d%s", time.Now().Unix(), file.Filename)
|
||||
|
||||
_, err := client.Object.Put(context.Background(), global.GLOBAL_CONFIG.TencentCOS.PathPrefix+"/"+fileKey, f, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return global.GLOBAL_CONFIG.TencentCOS.BaseURL + "/" + global.GLOBAL_CONFIG.TencentCOS.PathPrefix + "/" + fileKey, fileKey, nil
|
||||
}
|
||||
|
||||
// DeleteFile delete file form COS
|
||||
func (*TencentCOS) DeleteFile(key string) error {
|
||||
client := NewClient()
|
||||
name := global.GLOBAL_CONFIG.TencentCOS.PathPrefix + "/" + key
|
||||
_, err := client.Object.Delete(context.Background(), name)
|
||||
if err != nil {
|
||||
global.GLOBAL_LOG.Error("function bucketManager.Delete() Filed", zap.Any("err", err.Error()))
|
||||
return errors.New("function bucketManager.Delete() Filed, err:" + err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewClient init COS client
|
||||
func NewClient() *cos.Client {
|
||||
urlStr, _ := url.Parse("https://" + global.GLOBAL_CONFIG.TencentCOS.Bucket + ".cos." + global.GLOBAL_CONFIG.TencentCOS.Region + ".myqcloud.com")
|
||||
baseURL := &cos.BaseURL{BucketURL: urlStr}
|
||||
client := cos.NewClient(baseURL, &http.Client{
|
||||
Transport: &cos.AuthorizationTransport{
|
||||
SecretID: global.GLOBAL_CONFIG.TencentCOS.SecretID,
|
||||
SecretKey: global.GLOBAL_CONFIG.TencentCOS.SecretKey,
|
||||
},
|
||||
})
|
||||
return client
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package upload
|
||||
|
||||
import (
|
||||
"mime/multipart"
|
||||
|
||||
"goweb-gin-demo/global"
|
||||
)
|
||||
|
||||
//@author: [ccfish86](https://github.com/ccfish86)
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@interface_name: OSS
|
||||
//@description: OSS接口
|
||||
|
||||
type OSS interface {
|
||||
UploadFile(file *multipart.FileHeader) (string, string, error)
|
||||
DeleteFile(key string) error
|
||||
}
|
||||
|
||||
//@author: [ccfish86](https://github.com/ccfish86)
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@function: NewOss
|
||||
//@description: OSS接口
|
||||
//@description: OSS的实例化方法
|
||||
//@return: OSS
|
||||
|
||||
func NewOss() OSS {
|
||||
switch global.GLOBAL_CONFIG.System.OssType {
|
||||
case "local":
|
||||
return &Local{}
|
||||
case "qiniu":
|
||||
return &Qiniu{}
|
||||
case "tencent-cos":
|
||||
return &TencentCOS{}
|
||||
case "aliyun-oss":
|
||||
return &AliyunOSS{}
|
||||
default:
|
||||
return &Local{}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue