Finish the feature of share and bridge.
This commit is contained in:
9
code/core/application.go
Normal file
9
code/core/application.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从命令行输入的相关信息
|
||||||
|
*/
|
||||||
|
type Application interface {
|
||||||
|
//启动整个应用
|
||||||
|
Start()
|
||||||
|
}
|
@ -1,10 +0,0 @@
|
|||||||
package core
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 从命令行输入的相关信息
|
|
||||||
*/
|
|
||||||
type Command interface {
|
|
||||||
|
|
||||||
//判断是否为命名行模式,如果是直接按照命名行模式处理,并返回true。如果不是返回false.
|
|
||||||
Cli() bool
|
|
||||||
}
|
|
@ -3,7 +3,7 @@ package core
|
|||||||
//该文件中记录的是应用系统中全局变量。主要有日志LOGGER和上下文CONTEXT
|
//该文件中记录的是应用系统中全局变量。主要有日志LOGGER和上下文CONTEXT
|
||||||
|
|
||||||
//命令行输入等相关信息
|
//命令行输入等相关信息
|
||||||
var COMMAND Command
|
var APPLICATION Application
|
||||||
|
|
||||||
//日志系统必须高保
|
//日志系统必须高保
|
||||||
//全局唯一的日志对象(在main函数中初始化)
|
//全局唯一的日志对象(在main函数中初始化)
|
||||||
|
@ -10,6 +10,9 @@ import (
|
|||||||
const (
|
const (
|
||||||
TRUE = "true"
|
TRUE = "true"
|
||||||
FALSE = "false"
|
FALSE = "false"
|
||||||
|
|
||||||
|
DIRECTION_ASC = "ASC"
|
||||||
|
DIRECTION_DESC = "DESC"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IBase interface {
|
type IBase interface {
|
||||||
|
@ -1,89 +0,0 @@
|
|||||||
package rest
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/eyebluecn/tank/code/core"
|
|
||||||
"github.com/eyebluecn/tank/code/tool/builder"
|
|
||||||
"github.com/eyebluecn/tank/code/tool/result"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
type BridgeController struct {
|
|
||||||
BaseController
|
|
||||||
bridgeDao *BridgeDao
|
|
||||||
shareDao *ShareDao
|
|
||||||
bridgeService *BridgeService
|
|
||||||
}
|
|
||||||
|
|
||||||
//初始化方法
|
|
||||||
func (this *BridgeController) Init() {
|
|
||||||
this.BaseController.Init()
|
|
||||||
|
|
||||||
//手动装填本实例的Bean. 这里必须要用中间变量方可。
|
|
||||||
b := core.CONTEXT.GetBean(this.bridgeDao)
|
|
||||||
if b, ok := b.(*BridgeDao); ok {
|
|
||||||
this.bridgeDao = b
|
|
||||||
}
|
|
||||||
|
|
||||||
b = core.CONTEXT.GetBean(this.shareDao)
|
|
||||||
if b, ok := b.(*ShareDao); ok {
|
|
||||||
this.shareDao = b
|
|
||||||
}
|
|
||||||
b = core.CONTEXT.GetBean(this.bridgeService)
|
|
||||||
if b, ok := b.(*BridgeService); ok {
|
|
||||||
this.bridgeService = b
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//注册自己的路由。
|
|
||||||
func (this *BridgeController) RegisterRoutes() map[string]func(writer http.ResponseWriter, request *http.Request) {
|
|
||||||
|
|
||||||
routeMap := make(map[string]func(writer http.ResponseWriter, request *http.Request))
|
|
||||||
|
|
||||||
//每个Controller需要主动注册自己的路由。
|
|
||||||
routeMap["/api/bridge/page"] = this.Wrap(this.Page, USER_ROLE_USER)
|
|
||||||
|
|
||||||
return routeMap
|
|
||||||
}
|
|
||||||
|
|
||||||
//按照分页的方式查询
|
|
||||||
func (this *BridgeController) Page(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
|
||||||
|
|
||||||
//如果是根目录,那么就传入root.
|
|
||||||
pageStr := request.FormValue("page")
|
|
||||||
pageSizeStr := request.FormValue("pageSize")
|
|
||||||
shareUuid := request.FormValue("shareUuid")
|
|
||||||
orderCreateTime := request.FormValue("orderCreateTime")
|
|
||||||
orderSize := request.FormValue("orderSize")
|
|
||||||
|
|
||||||
share := this.shareDao.CheckByUuid(shareUuid)
|
|
||||||
|
|
||||||
var page int
|
|
||||||
if pageStr != "" {
|
|
||||||
page, _ = strconv.Atoi(pageStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
pageSize := 200
|
|
||||||
if pageSizeStr != "" {
|
|
||||||
tmp, err := strconv.Atoi(pageSizeStr)
|
|
||||||
if err == nil {
|
|
||||||
pageSize = tmp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sortArray := []builder.OrderPair{
|
|
||||||
{
|
|
||||||
Key: "create_time",
|
|
||||||
Value: orderCreateTime,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "size",
|
|
||||||
Value: orderSize,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
pager := this.bridgeDao.Page(page, pageSize, share.Uuid, sortArray)
|
|
||||||
|
|
||||||
return this.Success(pager)
|
|
||||||
}
|
|
@ -3,6 +3,7 @@ package rest
|
|||||||
import (
|
import (
|
||||||
"github.com/eyebluecn/tank/code/core"
|
"github.com/eyebluecn/tank/code/core"
|
||||||
"github.com/eyebluecn/tank/code/tool/builder"
|
"github.com/eyebluecn/tank/code/tool/builder"
|
||||||
|
"github.com/eyebluecn/tank/code/tool/result"
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
|
|
||||||
"github.com/nu7hatch/gouuid"
|
"github.com/nu7hatch/gouuid"
|
||||||
@ -37,6 +38,18 @@ func (this *BridgeDao) CheckByUuid(uuid string) *Bridge {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//按照shareUuid和matterUuid查找
|
||||||
|
func (this *BridgeDao) CheckByShareUuidAndMatterUuid(shareUuid string, matterUuid string) *Bridge {
|
||||||
|
|
||||||
|
// Read
|
||||||
|
var bridge Bridge
|
||||||
|
db := core.CONTEXT.GetDB().Where("share_uuid = ? AND matter_uuid = ?", shareUuid, matterUuid).First(&bridge)
|
||||||
|
this.PanicError(db.Error)
|
||||||
|
|
||||||
|
return &bridge
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//按分页条件获取分页
|
//按分页条件获取分页
|
||||||
func (this *BridgeDao) Page(page int, pageSize int, shareUuid string, sortArray []builder.OrderPair) *Pager {
|
func (this *BridgeDao) Page(page int, pageSize int, shareUuid string, sortArray []builder.OrderPair) *Pager {
|
||||||
|
|
||||||
@ -92,6 +105,47 @@ func (this *BridgeDao) Delete(bridge *Bridge) {
|
|||||||
this.PanicError(db.Error)
|
this.PanicError(db.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//删除一个matter对应的所有缓存
|
||||||
|
func (this *BridgeDao) DeleteByMatterUuid(matterUuid string) {
|
||||||
|
|
||||||
|
var wp = &builder.WherePair{}
|
||||||
|
|
||||||
|
wp = wp.And(&builder.WherePair{Query: "matter_uuid = ?", Args: []interface{}{matterUuid}})
|
||||||
|
|
||||||
|
//删除文件记录
|
||||||
|
db := core.CONTEXT.GetDB().Where(wp.Query, wp.Args).Delete(Bridge{})
|
||||||
|
this.PanicError(db.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除一个share对应的所有缓存
|
||||||
|
func (this *BridgeDao) DeleteByShareUuid(shareUuid string) {
|
||||||
|
|
||||||
|
var wp = &builder.WherePair{}
|
||||||
|
|
||||||
|
wp = wp.And(&builder.WherePair{Query: "share_uuid = ?", Args: []interface{}{shareUuid}})
|
||||||
|
|
||||||
|
//删除文件记录
|
||||||
|
db := core.CONTEXT.GetDB().Where(wp.Query, wp.Args).Delete(Bridge{})
|
||||||
|
this.PanicError(db.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据shareUuid获取关联的所有matter.
|
||||||
|
func (this *BridgeDao) ListByShareUuid(shareUuid string) []*Bridge {
|
||||||
|
|
||||||
|
if shareUuid == "" {
|
||||||
|
panic(result.BadRequest("shareUuid cannot be nil"))
|
||||||
|
}
|
||||||
|
|
||||||
|
var bridges []*Bridge
|
||||||
|
|
||||||
|
db := core.CONTEXT.GetDB().
|
||||||
|
Where("share_uuid = ?", shareUuid).
|
||||||
|
Find(&bridges)
|
||||||
|
this.PanicError(db.Error)
|
||||||
|
|
||||||
|
return bridges
|
||||||
|
}
|
||||||
|
|
||||||
//执行清理操作
|
//执行清理操作
|
||||||
func (this *BridgeDao) Cleanup() {
|
func (this *BridgeDao) Cleanup() {
|
||||||
this.logger.Info("[BridgeDao]执行清理:清除数据库中所有Bridge记录。")
|
this.logger.Info("[BridgeDao]执行清理:清除数据库中所有Bridge记录。")
|
||||||
|
@ -2,7 +2,6 @@ package rest
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/eyebluecn/tank/code/core"
|
"github.com/eyebluecn/tank/code/core"
|
||||||
"github.com/eyebluecn/tank/code/tool/builder"
|
"github.com/eyebluecn/tank/code/tool/builder"
|
||||||
"github.com/eyebluecn/tank/code/tool/result"
|
"github.com/eyebluecn/tank/code/tool/result"
|
||||||
@ -26,6 +25,7 @@ type InstallController struct {
|
|||||||
matterService *MatterService
|
matterService *MatterService
|
||||||
imageCacheDao *ImageCacheDao
|
imageCacheDao *ImageCacheDao
|
||||||
imageCacheService *ImageCacheService
|
imageCacheService *ImageCacheService
|
||||||
|
tableNames []IBase
|
||||||
}
|
}
|
||||||
|
|
||||||
//初始化方法
|
//初始化方法
|
||||||
@ -63,6 +63,20 @@ func (this *InstallController) Init() {
|
|||||||
this.imageCacheService = c
|
this.imageCacheService = c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.tableNames = []IBase{
|
||||||
|
&Dashboard{},
|
||||||
|
&Bridge{},
|
||||||
|
&DownloadToken{},
|
||||||
|
&Footprint{},
|
||||||
|
&ImageCache{},
|
||||||
|
&Matter{},
|
||||||
|
&Preference{},
|
||||||
|
&Session{},
|
||||||
|
&Share{},
|
||||||
|
&UploadToken{},
|
||||||
|
&User{},
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//注册自己的路由。
|
//注册自己的路由。
|
||||||
@ -185,10 +199,9 @@ func (this *InstallController) getTableMeta(gormDb *gorm.DB, entity IBase) (bool
|
|||||||
//根据表名获取建表SQL语句
|
//根据表名获取建表SQL语句
|
||||||
func (this *InstallController) getTableMetaList(db *gorm.DB) []*InstallTableInfo {
|
func (this *InstallController) getTableMetaList(db *gorm.DB) []*InstallTableInfo {
|
||||||
|
|
||||||
var tableNames = []IBase{&Dashboard{}, &DownloadToken{}, &Footprint{}, &ImageCache{}, &Matter{}, &Preference{}, &Session{}, &UploadToken{}, &User{}}
|
|
||||||
var installTableInfos []*InstallTableInfo
|
var installTableInfos []*InstallTableInfo
|
||||||
|
|
||||||
for _, iBase := range tableNames {
|
for _, iBase := range this.tableNames {
|
||||||
exist, allFields, missingFields := this.getTableMeta(db, iBase)
|
exist, allFields, missingFields := this.getTableMeta(db, iBase)
|
||||||
installTableInfos = append(installTableInfos, &InstallTableInfo{
|
installTableInfos = append(installTableInfos, &InstallTableInfo{
|
||||||
Name: iBase.TableName(),
|
Name: iBase.TableName(),
|
||||||
@ -247,13 +260,12 @@ func (this *InstallController) TableInfoList(writer http.ResponseWriter, request
|
|||||||
//创建缺失数据库和表
|
//创建缺失数据库和表
|
||||||
func (this *InstallController) CreateTable(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
func (this *InstallController) CreateTable(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||||
|
|
||||||
var tableNames = []IBase{&Dashboard{}, &DownloadToken{}, &Footprint{}, &ImageCache{}, &Matter{}, &Preference{}, &Session{}, &UploadToken{}, &User{}}
|
|
||||||
var installTableInfos []*InstallTableInfo
|
var installTableInfos []*InstallTableInfo
|
||||||
|
|
||||||
db := this.openDbConnection(writer, request)
|
db := this.openDbConnection(writer, request)
|
||||||
defer this.closeDbConnection(db)
|
defer this.closeDbConnection(db)
|
||||||
|
|
||||||
for _, iBase := range tableNames {
|
for _, iBase := range this.tableNames {
|
||||||
|
|
||||||
//补全缺失字段或者创建数据库表
|
//补全缺失字段或者创建数据库表
|
||||||
db1 := db.AutoMigrate(iBase)
|
db1 := db.AutoMigrate(iBase)
|
||||||
|
@ -15,6 +15,8 @@ type MatterController struct {
|
|||||||
matterService *MatterService
|
matterService *MatterService
|
||||||
downloadTokenDao *DownloadTokenDao
|
downloadTokenDao *DownloadTokenDao
|
||||||
imageCacheDao *ImageCacheDao
|
imageCacheDao *ImageCacheDao
|
||||||
|
shareDao *ShareDao
|
||||||
|
bridgeDao *BridgeDao
|
||||||
imageCacheService *ImageCacheService
|
imageCacheService *ImageCacheService
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,6 +44,12 @@ func (this *MatterController) Init() {
|
|||||||
if b, ok := b.(*ImageCacheDao); ok {
|
if b, ok := b.(*ImageCacheDao); ok {
|
||||||
this.imageCacheDao = b
|
this.imageCacheDao = b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b = core.CONTEXT.GetBean(this.shareDao)
|
||||||
|
if b, ok := b.(*ShareDao); ok {
|
||||||
|
this.shareDao = b
|
||||||
|
}
|
||||||
|
|
||||||
b = core.CONTEXT.GetBean(this.imageCacheService)
|
b = core.CONTEXT.GetBean(this.imageCacheService)
|
||||||
if b, ok := b.(*ImageCacheService); ok {
|
if b, ok := b.(*ImageCacheService); ok {
|
||||||
this.imageCacheService = b
|
this.imageCacheService = b
|
||||||
@ -64,7 +72,7 @@ func (this *MatterController) RegisterRoutes() map[string]func(writer http.Respo
|
|||||||
routeMap["/api/matter/change/privacy"] = this.Wrap(this.ChangePrivacy, USER_ROLE_USER)
|
routeMap["/api/matter/change/privacy"] = this.Wrap(this.ChangePrivacy, USER_ROLE_USER)
|
||||||
routeMap["/api/matter/move"] = this.Wrap(this.Move, USER_ROLE_USER)
|
routeMap["/api/matter/move"] = this.Wrap(this.Move, USER_ROLE_USER)
|
||||||
routeMap["/api/matter/detail"] = this.Wrap(this.Detail, USER_ROLE_USER)
|
routeMap["/api/matter/detail"] = this.Wrap(this.Detail, USER_ROLE_USER)
|
||||||
routeMap["/api/matter/page"] = this.Wrap(this.Page, USER_ROLE_USER)
|
routeMap["/api/matter/page"] = this.Wrap(this.Page, USER_ROLE_GUEST)
|
||||||
|
|
||||||
//本地文件映射
|
//本地文件映射
|
||||||
routeMap["/api/matter/mirror"] = this.Wrap(this.Mirror, USER_ROLE_USER)
|
routeMap["/api/matter/mirror"] = this.Wrap(this.Mirror, USER_ROLE_USER)
|
||||||
@ -114,9 +122,54 @@ func (this *MatterController) Page(writer http.ResponseWriter, request *http.Req
|
|||||||
orderName := request.FormValue("orderName")
|
orderName := request.FormValue("orderName")
|
||||||
extensionsStr := request.FormValue("extensions")
|
extensionsStr := request.FormValue("extensions")
|
||||||
|
|
||||||
user := this.checkUser(writer, request)
|
//使用分享提取码的形式授权。
|
||||||
if user.Role != USER_ROLE_ADMINISTRATOR {
|
shareUuid := request.FormValue("shareUuid")
|
||||||
userUuid = user.Uuid
|
shareCode := request.FormValue("shareCode")
|
||||||
|
shareRootUuid := request.FormValue("shareRootUuid")
|
||||||
|
if shareUuid != "" {
|
||||||
|
|
||||||
|
if puuid == "" {
|
||||||
|
panic(result.BadRequest("puuid必填!"))
|
||||||
|
}
|
||||||
|
dirMatter := this.matterDao.CheckByUuid(puuid)
|
||||||
|
if dirMatter.Dir {
|
||||||
|
panic(result.BadRequest("puuid 对应的不是文件夹"))
|
||||||
|
}
|
||||||
|
|
||||||
|
share := this.shareDao.CheckByUuid(shareUuid)
|
||||||
|
//如果是自己的分享,可以不要提取码
|
||||||
|
user := this.findUser(writer, request)
|
||||||
|
if user == nil {
|
||||||
|
if share.Code != shareCode {
|
||||||
|
panic(result.Unauthorized("提取码错误!"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if user.Uuid != share.UserUuid {
|
||||||
|
if share.Code != shareCode {
|
||||||
|
panic(result.Unauthorized("提取码错误!"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//验证 shareRootMatter是否在被分享。
|
||||||
|
shareRootMatter := this.matterDao.CheckByUuid(shareRootUuid)
|
||||||
|
if !shareRootMatter.Dir {
|
||||||
|
panic(result.BadRequest("只有文件夹可以浏览!"))
|
||||||
|
}
|
||||||
|
this.bridgeDao.CheckByShareUuidAndMatterUuid(share.Uuid, shareRootMatter.Uuid)
|
||||||
|
|
||||||
|
//保证 puuid对应的matter是shareRootMatter的子文件夹。
|
||||||
|
child := strings.HasPrefix(dirMatter.Path, shareRootMatter.Path)
|
||||||
|
if !child {
|
||||||
|
panic(result.BadRequest("%s 不是 %s 的子文件夹!", puuid, shareRootUuid))
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//非分享模式要求必须登录
|
||||||
|
user := this.checkUser(writer, request)
|
||||||
|
if user.Role != USER_ROLE_ADMINISTRATOR {
|
||||||
|
userUuid = user.Uuid
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var page int
|
var page int
|
||||||
@ -246,10 +299,10 @@ func (this *MatterController) Upload(writer http.ResponseWriter, request *http.R
|
|||||||
//从一个Url中去爬取资源
|
//从一个Url中去爬取资源
|
||||||
func (this *MatterController) Crawl(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
func (this *MatterController) Crawl(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||||
|
|
||||||
userUuid := request.FormValue("userUuid")
|
|
||||||
puuid := request.FormValue("puuid")
|
|
||||||
url := request.FormValue("url")
|
url := request.FormValue("url")
|
||||||
privacyStr := request.FormValue("privacy")
|
destPath := request.FormValue("destPath")
|
||||||
|
userUuid := request.FormValue("userUuid")
|
||||||
|
filename := request.FormValue("filename")
|
||||||
|
|
||||||
user := this.checkUser(writer, request)
|
user := this.checkUser(writer, request)
|
||||||
if user.Role != USER_ROLE_ADMINISTRATOR {
|
if user.Role != USER_ROLE_ADMINISTRATOR {
|
||||||
@ -262,23 +315,17 @@ func (this *MatterController) Crawl(writer http.ResponseWriter, request *http.Re
|
|||||||
|
|
||||||
user = this.userDao.CheckByUuid(userUuid)
|
user = this.userDao.CheckByUuid(userUuid)
|
||||||
|
|
||||||
dirMatter := this.matterDao.CheckWithRootByUuid(puuid, user)
|
dirMatter := this.matterService.CreateDirectories(user, destPath)
|
||||||
|
|
||||||
privacy := false
|
|
||||||
if privacyStr == TRUE {
|
|
||||||
privacy = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if url == "" || (!strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://")) {
|
if url == "" || (!strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://")) {
|
||||||
panic("资源url必填,并且应该以http://或者https://开头")
|
panic("资源url必填,并且应该以http://或者https://开头")
|
||||||
}
|
}
|
||||||
|
|
||||||
filename := request.FormValue("filename")
|
|
||||||
if filename == "" {
|
if filename == "" {
|
||||||
panic("文件名必传")
|
panic("filename 必填")
|
||||||
}
|
}
|
||||||
|
|
||||||
matter := this.matterService.AtomicCrawl(url, filename, user, dirMatter, privacy)
|
matter := this.matterService.AtomicCrawl(url, filename, user, dirMatter, true)
|
||||||
|
|
||||||
return this.Success(matter)
|
return this.Success(matter)
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
type MatterDao struct {
|
type MatterDao struct {
|
||||||
BaseDao
|
BaseDao
|
||||||
imageCacheDao *ImageCacheDao
|
imageCacheDao *ImageCacheDao
|
||||||
|
bridgeDao *BridgeDao
|
||||||
}
|
}
|
||||||
|
|
||||||
//初始化方法
|
//初始化方法
|
||||||
@ -25,6 +26,12 @@ func (this *MatterDao) Init() {
|
|||||||
if b, ok := b.(*ImageCacheDao); ok {
|
if b, ok := b.(*ImageCacheDao); ok {
|
||||||
this.imageCacheDao = b
|
this.imageCacheDao = b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b = core.CONTEXT.GetBean(this.bridgeDao)
|
||||||
|
if b, ok := b.(*BridgeDao); ok {
|
||||||
|
this.bridgeDao = b
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//按照Id查询文件
|
//按照Id查询文件
|
||||||
@ -220,6 +227,16 @@ func (this *MatterDao) List(puuid string, userUuid string, sortArray []builder.O
|
|||||||
return matters
|
return matters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//根据uuid查找对应的Matters
|
||||||
|
func (this *MatterDao) ListByUuids(puuids []string, sortArray []builder.OrderPair) []*Matter {
|
||||||
|
var matters []*Matter
|
||||||
|
|
||||||
|
db := core.CONTEXT.GetDB().Where(puuids).Order(this.GetSortString(sortArray)).Find(&matters)
|
||||||
|
this.PanicError(db.Error)
|
||||||
|
|
||||||
|
return matters
|
||||||
|
}
|
||||||
|
|
||||||
//获取某个文件夹下所有的文件和子文件
|
//获取某个文件夹下所有的文件和子文件
|
||||||
func (this *MatterDao) Page(page int, pageSize int, puuid string, userUuid string, name string, dir string, extensions []string, sortArray []builder.OrderPair) *Pager {
|
func (this *MatterDao) Page(page int, pageSize int, puuid string, userUuid string, name string, dir string, extensions []string, sortArray []builder.OrderPair) *Pager {
|
||||||
|
|
||||||
@ -325,6 +342,9 @@ func (this *MatterDao) Delete(matter *Matter) {
|
|||||||
//删除对应的缓存图片。
|
//删除对应的缓存图片。
|
||||||
this.imageCacheDao.DeleteByMatterUuid(matter.Uuid)
|
this.imageCacheDao.DeleteByMatterUuid(matter.Uuid)
|
||||||
|
|
||||||
|
//删除所有的分享文件
|
||||||
|
this.bridgeDao.DeleteByMatterUuid(matter.Uuid)
|
||||||
|
|
||||||
//删除文件
|
//删除文件
|
||||||
err := os.Remove(matter.AbsolutePath())
|
err := os.Remove(matter.AbsolutePath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -32,7 +32,7 @@ type Matter struct {
|
|||||||
Md5 string `json:"md5" gorm:"type:varchar(45)"`
|
Md5 string `json:"md5" gorm:"type:varchar(45)"`
|
||||||
Size int64 `json:"size" gorm:"type:bigint(20) not null;default:0"`
|
Size int64 `json:"size" gorm:"type:bigint(20) not null;default:0"`
|
||||||
Privacy bool `json:"privacy" gorm:"type:tinyint(1) not null;default:0"`
|
Privacy bool `json:"privacy" gorm:"type:tinyint(1) not null;default:0"`
|
||||||
Path string `json:"path" gorm:"type:varchar(512)"`
|
Path string `json:"path" gorm:"type:varchar(1024)"`
|
||||||
Times int64 `json:"times" gorm:"type:bigint(20) not null;default:0"`
|
Times int64 `json:"times" gorm:"type:bigint(20) not null;default:0"`
|
||||||
Parent *Matter `json:"parent" gorm:"-"`
|
Parent *Matter `json:"parent" gorm:"-"`
|
||||||
}
|
}
|
||||||
|
@ -797,6 +797,10 @@ func (this *MatterService) AtomicCrawl(url string, filename string, user *User,
|
|||||||
panic("资源url必填,并且应该以http://或者https://开头")
|
panic("资源url必填,并且应该以http://或者https://开头")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if filename == "" {
|
||||||
|
panic(result.BadRequest("filename cannot be null."))
|
||||||
|
}
|
||||||
|
|
||||||
//从指定的url下载一个文件。参考:https://golangcode.com/download-a-file-from-a-url/
|
//从指定的url下载一个文件。参考:https://golangcode.com/download-a-file-from-a-url/
|
||||||
resp, err := http.Get(url)
|
resp, err := http.Get(url)
|
||||||
this.PanicError(err)
|
this.PanicError(err)
|
||||||
|
@ -54,16 +54,19 @@ func (this *ShareController) RegisterRoutes() map[string]func(writer http.Respon
|
|||||||
//每个Controller需要主动注册自己的路由。
|
//每个Controller需要主动注册自己的路由。
|
||||||
routeMap["/api/share/create"] = this.Wrap(this.Create, USER_ROLE_USER)
|
routeMap["/api/share/create"] = this.Wrap(this.Create, USER_ROLE_USER)
|
||||||
routeMap["/api/share/delete"] = this.Wrap(this.Delete, USER_ROLE_USER)
|
routeMap["/api/share/delete"] = this.Wrap(this.Delete, USER_ROLE_USER)
|
||||||
|
routeMap["/api/share/delete/batch"] = this.Wrap(this.DeleteBatch, USER_ROLE_USER)
|
||||||
routeMap["/api/share/detail"] = this.Wrap(this.Detail, USER_ROLE_USER)
|
routeMap["/api/share/detail"] = this.Wrap(this.Detail, USER_ROLE_USER)
|
||||||
routeMap["/api/share/page"] = this.Wrap(this.Page, USER_ROLE_USER)
|
routeMap["/api/share/page"] = this.Wrap(this.Page, USER_ROLE_USER)
|
||||||
|
routeMap["/api/share/browse"] = this.Wrap(this.Browse, USER_ROLE_GUEST)
|
||||||
|
|
||||||
return routeMap
|
return routeMap
|
||||||
}
|
}
|
||||||
|
|
||||||
//删除一条记录
|
//创建一个分享
|
||||||
func (this *ShareController) Create(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
func (this *ShareController) Create(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||||
|
|
||||||
matterUuids := request.FormValue("matterUuids")
|
matterUuids := request.FormValue("matterUuids")
|
||||||
|
expireInfinityStr := request.FormValue("expireInfinity")
|
||||||
expireTimeStr := request.FormValue("expireTime")
|
expireTimeStr := request.FormValue("expireTime")
|
||||||
|
|
||||||
if matterUuids == "" {
|
if matterUuids == "" {
|
||||||
@ -71,47 +74,86 @@ func (this *ShareController) Create(writer http.ResponseWriter, request *http.Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
var expireTime time.Time
|
var expireTime time.Time
|
||||||
if expireTimeStr == "" {
|
expireInfinity := false
|
||||||
panic(result.BadRequest("时间格式错误!"))
|
if expireInfinityStr == TRUE {
|
||||||
|
expireInfinity = true
|
||||||
|
expireTime = time.Now()
|
||||||
} else {
|
} else {
|
||||||
expireTime = util.ConvertDateTimeStringToTime(expireTimeStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if expireTime.Before(time.Now()) {
|
if expireTimeStr == "" {
|
||||||
panic(result.BadRequest("过期时间错误!"))
|
panic(result.BadRequest("时间格式错误!"))
|
||||||
|
} else {
|
||||||
|
expireTime = util.ConvertDateTimeStringToTime(expireTimeStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if expireTime.Before(time.Now()) {
|
||||||
|
panic(result.BadRequest("过期时间错误!"))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uuidArray := strings.Split(matterUuids, ",")
|
uuidArray := strings.Split(matterUuids, ",")
|
||||||
|
|
||||||
if len(uuidArray) == 0 {
|
if len(uuidArray) == 0 {
|
||||||
panic(result.BadRequest("请至少分享一个文件"))
|
panic(result.BadRequest("请至少分享一个文件"))
|
||||||
|
} else if len(uuidArray) > SHARE_MAX_NUM {
|
||||||
|
panic(result.BadRequest("一次分享文件数不能超过 %d", SHARE_MAX_NUM))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var name string
|
||||||
|
shareType := SHARE_TYPE_MIX
|
||||||
user := this.checkUser(writer, request)
|
user := this.checkUser(writer, request)
|
||||||
for _, uuid := range uuidArray {
|
var puuid string
|
||||||
|
var matters []*Matter
|
||||||
|
for key, uuid := range uuidArray {
|
||||||
|
|
||||||
matter := this.matterDao.CheckByUuid(uuid)
|
matter := this.matterDao.CheckByUuid(uuid)
|
||||||
|
|
||||||
//判断文件的所属人是否正确
|
//判断文件的所属人是否正确
|
||||||
if matter.UserUuid != user.Uuid {
|
if matter.UserUuid != user.Uuid {
|
||||||
panic(result.Unauthorized("没有权限"))
|
panic(result.Unauthorized("不是你的文件,没有权限"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
matters = append(matters, matter)
|
||||||
|
|
||||||
|
if key == 0 {
|
||||||
|
puuid = matter.Puuid
|
||||||
|
name = matter.Name
|
||||||
|
if matter.Dir {
|
||||||
|
shareType = SHARE_TYPE_DIRECTORY
|
||||||
|
} else {
|
||||||
|
shareType = SHARE_TYPE_FILE
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if matter.Puuid != puuid {
|
||||||
|
panic(result.Unauthorized("一次只能分享同一个文件夹中的内容"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(uuidArray) > 1 {
|
||||||
|
shareType = SHARE_TYPE_MIX
|
||||||
|
name = name + "等"
|
||||||
}
|
}
|
||||||
|
|
||||||
//创建share记录
|
//创建share记录
|
||||||
share := &Share{
|
share := &Share{
|
||||||
UserUuid: user.Uuid,
|
Name: name,
|
||||||
DownloadTimes: 0,
|
ShareType: shareType,
|
||||||
Code: util.RandomString4(),
|
UserUuid: user.Uuid,
|
||||||
ExpireTime: expireTime,
|
DownloadTimes: 0,
|
||||||
|
Code: util.RandomString4(),
|
||||||
|
ExpireInfinity: expireInfinity,
|
||||||
|
ExpireTime: expireTime,
|
||||||
}
|
}
|
||||||
this.shareDao.Create(share)
|
this.shareDao.Create(share)
|
||||||
|
|
||||||
//创建关联的matter
|
//创建关联的matter
|
||||||
for _, matterUuid := range uuidArray {
|
for _, matter := range matters {
|
||||||
bridge := &Bridge{
|
bridge := &Bridge{
|
||||||
ShareUuid: share.Uuid,
|
ShareUuid: share.Uuid,
|
||||||
MatterUuid: matterUuid,
|
MatterUuid: matter.Uuid,
|
||||||
}
|
}
|
||||||
this.bridgeDao.Create(bridge)
|
this.bridgeDao.Create(bridge)
|
||||||
}
|
}
|
||||||
@ -130,12 +172,42 @@ func (this *ShareController) Delete(writer http.ResponseWriter, request *http.Re
|
|||||||
share := this.shareDao.FindByUuid(uuid)
|
share := this.shareDao.FindByUuid(uuid)
|
||||||
|
|
||||||
if share != nil {
|
if share != nil {
|
||||||
|
|
||||||
|
//删除对应的bridge.
|
||||||
|
this.bridgeDao.DeleteByShareUuid(share.Uuid)
|
||||||
|
|
||||||
this.shareDao.Delete(share)
|
this.shareDao.Delete(share)
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.Success(nil)
|
return this.Success(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//删除一系列分享
|
||||||
|
func (this *ShareController) DeleteBatch(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||||
|
|
||||||
|
uuids := request.FormValue("uuids")
|
||||||
|
if uuids == "" {
|
||||||
|
panic(result.BadRequest("uuids必填"))
|
||||||
|
}
|
||||||
|
|
||||||
|
uuidArray := strings.Split(uuids, ",")
|
||||||
|
|
||||||
|
for _, uuid := range uuidArray {
|
||||||
|
|
||||||
|
imageCache := this.shareDao.FindByUuid(uuid)
|
||||||
|
|
||||||
|
//判断图片缓存的所属人是否正确
|
||||||
|
user := this.checkUser(writer, request)
|
||||||
|
if user.Role != USER_ROLE_ADMINISTRATOR && imageCache.UserUuid != user.Uuid {
|
||||||
|
panic(result.Unauthorized("没有权限"))
|
||||||
|
}
|
||||||
|
|
||||||
|
this.shareDao.Delete(imageCache)
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.Success("删除成功!")
|
||||||
|
}
|
||||||
|
|
||||||
//查看详情。
|
//查看详情。
|
||||||
func (this *ShareController) Detail(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
func (this *ShareController) Detail(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||||
|
|
||||||
@ -196,3 +268,59 @@ func (this *ShareController) Page(writer http.ResponseWriter, request *http.Requ
|
|||||||
|
|
||||||
return this.Success(pager)
|
return this.Success(pager)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//验证提取码对应的某个shareUuid是否有效
|
||||||
|
func (this *ShareController) CheckShare(writer http.ResponseWriter, request *http.Request) *Share {
|
||||||
|
|
||||||
|
//如果是根目录,那么就传入root.
|
||||||
|
shareUuid := request.FormValue("shareUuid")
|
||||||
|
code := request.FormValue("code")
|
||||||
|
|
||||||
|
share := this.shareDao.CheckByUuid(shareUuid)
|
||||||
|
//如果是自己的分享,可以不要提取码
|
||||||
|
user := this.findUser(writer, request)
|
||||||
|
if user == nil {
|
||||||
|
if share.Code != code {
|
||||||
|
panic(result.Unauthorized("提取码错误!"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if user.Uuid != share.UserUuid {
|
||||||
|
if share.Code != code {
|
||||||
|
panic(result.Unauthorized("提取码错误!"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return share
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//浏览某个分享中的文件
|
||||||
|
func (this *ShareController) Browse(writer http.ResponseWriter, request *http.Request) *result.WebResult {
|
||||||
|
|
||||||
|
//要求传参:shareUuid,code
|
||||||
|
share := this.CheckShare(writer, request)
|
||||||
|
bridges := this.bridgeDao.ListByShareUuid(share.Uuid)
|
||||||
|
|
||||||
|
//获取对应的 matter.
|
||||||
|
var matters []*Matter
|
||||||
|
if len(bridges) != 0 {
|
||||||
|
uuids := make([]string, 0)
|
||||||
|
for _, bridge := range bridges {
|
||||||
|
uuids = append(uuids, bridge.MatterUuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
sortArray := []builder.OrderPair{
|
||||||
|
{
|
||||||
|
Key: "dir",
|
||||||
|
Value: DIRECTION_DESC,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
matters = this.matterDao.ListByUuids(uuids, sortArray)
|
||||||
|
|
||||||
|
share.Matters = matters
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.Success(share)
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -90,6 +90,7 @@ func (this *ShareDao) Delete(share *Share) {
|
|||||||
|
|
||||||
db := core.CONTEXT.GetDB().Delete(&share)
|
db := core.CONTEXT.GetDB().Delete(&share)
|
||||||
this.PanicError(db.Error)
|
this.PanicError(db.Error)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//执行清理操作
|
//执行清理操作
|
||||||
|
@ -5,15 +5,32 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
//单文件
|
||||||
|
SHARE_TYPE_FILE = "FILE"
|
||||||
|
//文件夹
|
||||||
|
SHARE_TYPE_DIRECTORY = "DIRECTORY"
|
||||||
|
//混合体
|
||||||
|
SHARE_TYPE_MIX = "MIX"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SHARE_MAX_NUM = 100
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分享记录
|
* 分享记录
|
||||||
*/
|
*/
|
||||||
type Share struct {
|
type Share struct {
|
||||||
Base
|
Base
|
||||||
UserUuid string `json:"userUuid" gorm:"type:char(36)"`
|
Name string `json:"name" gorm:"type:varchar(255)"`
|
||||||
DownloadTimes int64 `json:"downloadTimes" gorm:"type:bigint(20) not null;default:0"`
|
ShareType string `json:"shareType" gorm:"type:varchar(45)"`
|
||||||
Code string `json:"code" gorm:"type:varchar(45) not null"`
|
UserUuid string `json:"userUuid" gorm:"type:char(36)"`
|
||||||
ExpireTime time.Time `json:"expireTime" gorm:"type:timestamp not null;default:'2018-01-01 00:00:00'"`
|
DownloadTimes int64 `json:"downloadTimes" gorm:"type:bigint(20) not null;default:0"`
|
||||||
|
Code string `json:"code" gorm:"type:varchar(45) not null"`
|
||||||
|
ExpireInfinity bool `json:"expireInfinity" gorm:"type:tinyint(1) not null;default:0"`
|
||||||
|
ExpireTime time.Time `json:"expireTime" gorm:"type:timestamp not null;default:'2018-01-01 00:00:00'"`
|
||||||
|
Matters []*Matter `json:"matters" gorm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// set File's table name to be `profiles`
|
// set File's table name to be `profiles`
|
||||||
|
256
code/support/tank_application.go
Normal file
256
code/support/tank_application.go
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
package support
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"github.com/eyebluecn/tank/code/core"
|
||||||
|
"github.com/eyebluecn/tank/code/tool/result"
|
||||||
|
"github.com/eyebluecn/tank/code/tool/util"
|
||||||
|
jsoniter "github.com/json-iterator/go"
|
||||||
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
//启动web服务,默认是这种方式
|
||||||
|
MODE_WEB = "web"
|
||||||
|
//映射本地文件到云盘中
|
||||||
|
MODE_MIRROR = "mirror"
|
||||||
|
//将远程的一个文件爬取到蓝眼云盘中
|
||||||
|
MODE_CRAWL = "crawl"
|
||||||
|
)
|
||||||
|
|
||||||
|
//命令行输入相关的对象
|
||||||
|
type TankApplication struct {
|
||||||
|
//模式
|
||||||
|
mode string
|
||||||
|
|
||||||
|
//蓝眼云盘的主机,需要带上协议和端口号。默认: http://127.0.0.1:core.DEFAULT_SERVER_PORT
|
||||||
|
host string
|
||||||
|
//用户名
|
||||||
|
username string
|
||||||
|
//密码
|
||||||
|
password string
|
||||||
|
|
||||||
|
//源文件/文件夹,本地绝对路径/远程资源url
|
||||||
|
src string
|
||||||
|
//目标(表示的是文件夹)路径,蓝眼云盘中的路径。相对于root的路径。
|
||||||
|
dest string
|
||||||
|
//同名文件或文件夹是否直接替换 true 全部替换; false 跳过
|
||||||
|
overwrite bool
|
||||||
|
//拉取文件存储的名称
|
||||||
|
filename string
|
||||||
|
}
|
||||||
|
|
||||||
|
//启动应用。可能是web形式,也可能是命令行工具。
|
||||||
|
func (this *TankApplication) Start() {
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
fmt.Printf("ERROR:%v\r\n", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
//超级管理员信息
|
||||||
|
modePtr := flag.String("mode", this.mode, "cli mode web/mirror/crawl")
|
||||||
|
hostPtr := flag.String("host", this.username, "tank host")
|
||||||
|
usernamePtr := flag.String("username", this.username, "username")
|
||||||
|
passwordPtr := flag.String("password", this.password, "password")
|
||||||
|
srcPtr := flag.String("src", this.src, "src absolute path")
|
||||||
|
destPtr := flag.String("dest", this.dest, "destination path in tank.")
|
||||||
|
overwritePtr := flag.Bool("overwrite", this.overwrite, "whether same file overwrite")
|
||||||
|
filenamePtr := flag.String("filename", this.filename, "filename when crawl")
|
||||||
|
|
||||||
|
//flag.Parse()方法必须要在使用之前调用。
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
this.mode = *modePtr
|
||||||
|
this.host = *hostPtr
|
||||||
|
this.username = *usernamePtr
|
||||||
|
this.password = *passwordPtr
|
||||||
|
this.src = *srcPtr
|
||||||
|
this.dest = *destPtr
|
||||||
|
this.overwrite = *overwritePtr
|
||||||
|
this.filename = *filenamePtr
|
||||||
|
|
||||||
|
//默认采用web的形式启动
|
||||||
|
if this.mode == "" || strings.ToLower(this.mode) == MODE_WEB {
|
||||||
|
|
||||||
|
//直接web启动
|
||||||
|
this.HandleWeb()
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
//准备蓝眼云盘地址
|
||||||
|
if this.host == "" {
|
||||||
|
this.host = fmt.Sprintf("http://127.0.0.1:%d", core.DEFAULT_SERVER_PORT)
|
||||||
|
}
|
||||||
|
|
||||||
|
//准备用户名
|
||||||
|
if this.username == "" {
|
||||||
|
panic(result.BadRequest("%s模式下,用户名必填", this.mode))
|
||||||
|
}
|
||||||
|
|
||||||
|
//准备密码
|
||||||
|
if this.password == "" {
|
||||||
|
|
||||||
|
if util.EnvDevelopment() {
|
||||||
|
|
||||||
|
panic(result.BadRequest("IDE中请运行请直接使用 -password yourPassword 的形式输入密码"))
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
fmt.Print("Enter Password:")
|
||||||
|
bytePassword, err := terminal.ReadPassword(int(syscall.Stdin))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.password = string(bytePassword)
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.ToLower(this.mode) == MODE_MIRROR {
|
||||||
|
|
||||||
|
//映射本地文件到蓝眼云盘
|
||||||
|
this.HandleMirror()
|
||||||
|
|
||||||
|
} else if strings.ToLower(this.mode) == MODE_CRAWL {
|
||||||
|
|
||||||
|
//将远程文件拉取到蓝眼云盘中
|
||||||
|
this.HandleCrawl()
|
||||||
|
|
||||||
|
} else {
|
||||||
|
panic(result.BadRequest("不能处理命名行模式: %s \r\n", this.mode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//采用Web的方式启动应用
|
||||||
|
func (this *TankApplication) HandleWeb() {
|
||||||
|
|
||||||
|
//第1步。日志
|
||||||
|
tankLogger := &TankLogger{}
|
||||||
|
core.LOGGER = tankLogger
|
||||||
|
tankLogger.Init()
|
||||||
|
defer tankLogger.Destroy()
|
||||||
|
|
||||||
|
//第2步。配置
|
||||||
|
tankConfig := &TankConfig{}
|
||||||
|
core.CONFIG = tankConfig
|
||||||
|
tankConfig.Init()
|
||||||
|
|
||||||
|
//第3步。全局运行的上下文
|
||||||
|
tankContext := &TankContext{}
|
||||||
|
core.CONTEXT = tankContext
|
||||||
|
tankContext.Init()
|
||||||
|
defer tankContext.Destroy()
|
||||||
|
|
||||||
|
//第4步。启动http服务
|
||||||
|
http.Handle("/", core.CONTEXT)
|
||||||
|
core.LOGGER.Info("App started at http://localhost:%v", core.CONFIG.ServerPort())
|
||||||
|
|
||||||
|
dotPort := fmt.Sprintf(":%v", core.CONFIG.ServerPort())
|
||||||
|
err1 := http.ListenAndServe(dotPort, nil)
|
||||||
|
if err1 != nil {
|
||||||
|
log.Fatal("ListenAndServe: ", err1)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//处理本地映射的情形
|
||||||
|
func (this *TankApplication) HandleMirror() {
|
||||||
|
|
||||||
|
if this.src == "" {
|
||||||
|
panic("src 必填")
|
||||||
|
}
|
||||||
|
if this.dest == "" {
|
||||||
|
panic("dest 必填")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("开始映射本地文件 %s 到蓝眼云盘 %s\r\n", this.src, this.dest)
|
||||||
|
|
||||||
|
urlString := fmt.Sprintf("%s/api/matter/mirror", this.host)
|
||||||
|
|
||||||
|
params := url.Values{
|
||||||
|
"srcPath": {this.src},
|
||||||
|
"destPath": {this.dest},
|
||||||
|
"overwrite": {fmt.Sprintf("%v", this.overwrite)},
|
||||||
|
core.USERNAME_KEY: {this.username},
|
||||||
|
core.PASSWORD_KEY: {this.password},
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := http.PostForm(urlString, params)
|
||||||
|
util.PanicError(err)
|
||||||
|
|
||||||
|
bodyBytes, err := ioutil.ReadAll(response.Body)
|
||||||
|
|
||||||
|
webResult := &result.WebResult{}
|
||||||
|
|
||||||
|
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(bodyBytes, webResult)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("返回格式错误!%s \r\n", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if webResult.Code == result.CODE_WRAPPER_OK.Code {
|
||||||
|
fmt.Println("success")
|
||||||
|
} else {
|
||||||
|
fmt.Printf("error %s\r\n", webResult.Msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//拉取远程文件到本地。
|
||||||
|
func (this *TankApplication) HandleCrawl() {
|
||||||
|
|
||||||
|
if this.src == "" {
|
||||||
|
panic("src 必填")
|
||||||
|
}
|
||||||
|
if this.dest == "" {
|
||||||
|
panic("dest 必填")
|
||||||
|
}
|
||||||
|
|
||||||
|
if this.filename == "" {
|
||||||
|
panic("filename 必填")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("开始映射拉取远程文件 %s 到蓝眼云盘 %s\r\n", this.src, this.dest)
|
||||||
|
|
||||||
|
urlString := fmt.Sprintf("%s/api/matter/crawl", this.host)
|
||||||
|
|
||||||
|
params := url.Values{
|
||||||
|
"url": {this.src},
|
||||||
|
"destPath": {this.dest},
|
||||||
|
"filename": {this.filename},
|
||||||
|
core.USERNAME_KEY: {this.username},
|
||||||
|
core.PASSWORD_KEY: {this.password},
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := http.PostForm(urlString, params)
|
||||||
|
util.PanicError(err)
|
||||||
|
|
||||||
|
bodyBytes, err := ioutil.ReadAll(response.Body)
|
||||||
|
|
||||||
|
webResult := &result.WebResult{}
|
||||||
|
|
||||||
|
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(bodyBytes, webResult)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("返回格式错误!%s \r\n", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if webResult.Code == result.CODE_WRAPPER_OK.Code {
|
||||||
|
fmt.Println("success")
|
||||||
|
} else {
|
||||||
|
fmt.Printf("error %s\r\n", webResult.Msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,151 +0,0 @@
|
|||||||
package support
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"github.com/eyebluecn/tank/code/core"
|
|
||||||
"github.com/eyebluecn/tank/code/tool/result"
|
|
||||||
"github.com/eyebluecn/tank/code/tool/util"
|
|
||||||
jsoniter "github.com/json-iterator/go"
|
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
//启动web服务,默认是这种方式
|
|
||||||
MODE_WEB = "web"
|
|
||||||
//映射本地文件到云盘中
|
|
||||||
MODE_MIRROR = "mirror"
|
|
||||||
)
|
|
||||||
|
|
||||||
//命令行输入相关的对象
|
|
||||||
type TankCommand struct {
|
|
||||||
//模式
|
|
||||||
mode string
|
|
||||||
|
|
||||||
//蓝眼云盘的主机,需要带上协议和端口号。默认: http://127.0.0.1:core.DEFAULT_SERVER_PORT
|
|
||||||
host string
|
|
||||||
//用户名
|
|
||||||
username string
|
|
||||||
//密码
|
|
||||||
password string
|
|
||||||
|
|
||||||
//源文件/文件夹,本地绝对路径
|
|
||||||
src string
|
|
||||||
//目标(表示的是文件夹)路径,蓝眼云盘中的路径。相对于root的路径。
|
|
||||||
dest string
|
|
||||||
//同名文件或文件夹是否直接替换 true 全部替换; false 跳过
|
|
||||||
overwrite bool
|
|
||||||
}
|
|
||||||
|
|
||||||
//第三级. 从程序参数中读取配置项
|
|
||||||
func (this *TankCommand) Cli() bool {
|
|
||||||
|
|
||||||
//超级管理员信息
|
|
||||||
modePtr := flag.String("mode", this.mode, "cli mode web/mirror")
|
|
||||||
hostPtr := flag.String("host", this.username, "tank host")
|
|
||||||
usernamePtr := flag.String("username", this.username, "username")
|
|
||||||
passwordPtr := flag.String("password", this.password, "password")
|
|
||||||
srcPtr := flag.String("src", this.src, "src absolute path")
|
|
||||||
destPtr := flag.String("dest", this.dest, "destination path in tank.")
|
|
||||||
overwritePtr := flag.Bool("overwrite", this.overwrite, "whether same file overwrite")
|
|
||||||
|
|
||||||
//flag.Parse()方法必须要在使用之前调用。
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
this.mode = *modePtr
|
|
||||||
this.host = *hostPtr
|
|
||||||
this.username = *usernamePtr
|
|
||||||
this.password = *passwordPtr
|
|
||||||
this.src = *srcPtr
|
|
||||||
this.dest = *destPtr
|
|
||||||
this.overwrite = *overwritePtr
|
|
||||||
|
|
||||||
//准备模式
|
|
||||||
if this.mode == "" || strings.ToLower(this.mode) == MODE_WEB {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
//准备蓝眼云盘地址
|
|
||||||
if this.host == "" {
|
|
||||||
this.host = fmt.Sprintf("http://127.0.0.1:%d", core.DEFAULT_SERVER_PORT)
|
|
||||||
}
|
|
||||||
|
|
||||||
//准备用户名
|
|
||||||
if this.username == "" {
|
|
||||||
fmt.Println("用户名必填")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
//准备密码
|
|
||||||
if this.password == "" {
|
|
||||||
|
|
||||||
if util.EnvDevelopment() {
|
|
||||||
|
|
||||||
fmt.Println("IDE中请运行请直接使用 -password yourPassword 的形式输入密码")
|
|
||||||
return true
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
fmt.Print("Enter Password:")
|
|
||||||
bytePassword, err := terminal.ReadPassword(int(syscall.Stdin))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.password = string(bytePassword)
|
|
||||||
fmt.Println()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.ToLower(this.mode) == MODE_MIRROR {
|
|
||||||
|
|
||||||
this.HandleMirror()
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
fmt.Printf("不能处理命名行模式: %s \r\n", this.mode)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
//处理本地映射的情形
|
|
||||||
func (this *TankCommand) HandleMirror() {
|
|
||||||
|
|
||||||
fmt.Printf("开始映射本地文件 %s 到蓝眼云盘 %s\r\n", this.src, this.dest)
|
|
||||||
|
|
||||||
urlString := fmt.Sprintf("%s/api/matter/mirror", this.host)
|
|
||||||
|
|
||||||
params := url.Values{
|
|
||||||
"srcPath": {this.src},
|
|
||||||
"destPath": {this.dest},
|
|
||||||
"overwrite": {fmt.Sprintf("%v", this.overwrite)},
|
|
||||||
core.USERNAME_KEY: {this.username},
|
|
||||||
core.PASSWORD_KEY: {this.password},
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := http.PostForm(urlString, params)
|
|
||||||
util.PanicError(err)
|
|
||||||
|
|
||||||
bodyBytes, err := ioutil.ReadAll(response.Body)
|
|
||||||
|
|
||||||
webResult := &result.WebResult{}
|
|
||||||
|
|
||||||
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(bodyBytes, webResult)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("返回格式错误!%s \r\n", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if webResult.Code == result.CODE_WRAPPER_OK.Code {
|
|
||||||
fmt.Println("success")
|
|
||||||
} else {
|
|
||||||
fmt.Printf("error %s\r\n", webResult.Msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -131,7 +131,6 @@ func (this *TankContext) registerBeans() {
|
|||||||
this.registerBean(new(rest.AlienService))
|
this.registerBean(new(rest.AlienService))
|
||||||
|
|
||||||
//bridge
|
//bridge
|
||||||
this.registerBean(new(rest.BridgeController))
|
|
||||||
this.registerBean(new(rest.BridgeDao))
|
this.registerBean(new(rest.BridgeDao))
|
||||||
this.registerBean(new(rest.BridgeService))
|
this.registerBean(new(rest.BridgeService))
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -72,7 +73,13 @@ func NewRouter() *TankRouter {
|
|||||||
func (this *TankRouter) GlobalPanicHandler(writer http.ResponseWriter, request *http.Request, startTime time.Time) {
|
func (this *TankRouter) GlobalPanicHandler(writer http.ResponseWriter, request *http.Request, startTime time.Time) {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
|
|
||||||
core.LOGGER.Error("错误: %v", err)
|
//控制台中打印日志,记录行号。
|
||||||
|
_, file, line, ok := runtime.Caller(2)
|
||||||
|
if !ok {
|
||||||
|
file = "???"
|
||||||
|
line = 0
|
||||||
|
}
|
||||||
|
core.LOGGER.Error("panic on %s:%d %v", util.GetFilenameOfPath(file), line, err)
|
||||||
|
|
||||||
var webResult *result.WebResult = nil
|
var webResult *result.WebResult = nil
|
||||||
if value, ok := err.(string); ok {
|
if value, ok := err.(string); ok {
|
||||||
|
@ -51,7 +51,8 @@ func RandomNumber4() string {
|
|||||||
//获取四位随机数字
|
//获取四位随机数字
|
||||||
func RandomString4() string {
|
func RandomString4() string {
|
||||||
|
|
||||||
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz0123456789")
|
//0和o,l和1难以区分,剔除掉
|
||||||
|
var letterRunes = []rune("abcdefghijkmnpqrstuvwxyz23456789")
|
||||||
|
|
||||||
b := make([]rune, 4)
|
b := make([]rune, 4)
|
||||||
for i := range b {
|
for i := range b {
|
||||||
|
37
main.go
37
main.go
@ -1,47 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/eyebluecn/tank/code/core"
|
"github.com/eyebluecn/tank/code/core"
|
||||||
"github.com/eyebluecn/tank/code/support"
|
"github.com/eyebluecn/tank/code/support"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
//第一步。命令行工具处理
|
core.APPLICATION = &support.TankApplication{}
|
||||||
tankCommand := &support.TankCommand{}
|
core.APPLICATION.Start()
|
||||||
core.COMMAND = tankCommand
|
|
||||||
if core.COMMAND.Cli() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//第二步。日志
|
|
||||||
tankLogger := &support.TankLogger{}
|
|
||||||
core.LOGGER = tankLogger
|
|
||||||
tankLogger.Init()
|
|
||||||
defer tankLogger.Destroy()
|
|
||||||
|
|
||||||
//第三步。配置
|
|
||||||
tankConfig := &support.TankConfig{}
|
|
||||||
core.CONFIG = tankConfig
|
|
||||||
tankConfig.Init()
|
|
||||||
|
|
||||||
//第四步。全局运行的上下文
|
|
||||||
tankContext := &support.TankContext{}
|
|
||||||
core.CONTEXT = tankContext
|
|
||||||
tankContext.Init()
|
|
||||||
defer tankContext.Destroy()
|
|
||||||
|
|
||||||
//第五步。启动http服务
|
|
||||||
http.Handle("/", core.CONTEXT)
|
|
||||||
core.LOGGER.Info("App started at http://localhost:%v", core.CONFIG.ServerPort())
|
|
||||||
|
|
||||||
dotPort := fmt.Sprintf(":%v", core.CONFIG.ServerPort())
|
|
||||||
err1 := http.ListenAndServe(dotPort, nil)
|
|
||||||
if err1 != nil {
|
|
||||||
log.Fatal("ListenAndServe: ", err1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user