DocHub分析

  • A+
所属分类:系统文档

基础教程

go goweb

centos 安装go

参考
https://github.com/zcorky/zgvm

wget -qO- https://raw.githubusercontent.com/zcorky/zgvm/master/install | bash   
zgvm install v1.18   
source ~/.bashrc 

如果无法访问raw.githubusercontent.com 可以看解决办法

beego安装

go get  github.com/beego/bee/v2
go install github.com/beego/bee/v2  

go get github.com/astaxie/beego  
go install github.com/astaxie/beego 

Dochub安装

#环境go版本 go1.17 ,新版本应该也行。
# 在你的目录执行下载的命令就行,按顺序
git clone https://gitee.com/truthhun/DocHub
# 进入程序目录
cd DocHub
# 安装依赖包
go mod init Dochub
go mod tidy
go mod vendor
# 编译源码
go build
#执行完会在当前目录下生成
Dochub或者Dochub.exe
git clone https://gitee.com/truthhun/DocHub.git 
cd DocHub  
go mod init  # 初始化
go  build -o hello main.go  # 会提示缺少哪些依赖  进行安装 即可 

go get github.com/astaxie/beego 
go get github.com/TruthHun/DocHub/controllers/HomeControllers  

运行调试代码

DocHub代码学习

安装分析

安装后,直接请求,会跳转到/install 路径

首先在router.go的init中,判断如果helper.IsInstalled 为false 并且请求的路径不是/install 则会跳转到安装路径

helper.IsInstalled 默认是为false,在helper.go的init中判断, 如果存在 conf/app.conf 则表示安装过,将 helper.IsInstalled 设置为true

因此如果已经安装过,则直接将 conf/app.conf复制过来即可
但是这样操作后,登录时无法通过csrf校验 还没有搞清楚什么原因 在 \adapter\context\context.go文件中返回417错误状态码
先在conf/app.conf中将关闭csrf防护 enablexsrf = false

根据router.go设置,请求/install 则 HomeControllers目录下InstallController.go文件Install函数进行响应

  • GET请求,直接显示页面
  • POST请求 判断数据库账号和密码是否正确
  • 初始化 生成 conf/app.conf 文件 ,内容在config.go 的GenerateAppConf 函数中,存储
  • 加载conf/app.conf成功后,models/Models.go中的Init函数,创建数据库,models/Install.go中的install函数 插入相关数据
  • 然后在models/SeoModel.go文件的AutoSitemap函数,生成站点信息,并且是死循环监听,到时间后重新生成
    至此安装流程结束

提交请求时static\Home\default\js\dochub.js 在.wenku-ajax-form [type=submit] 进行处理

上传文档功能

  • 先调用 segwd 路径进行分词操作
    分词成功后,变成标签显示在界面上
  • 文件上传处理流程 官方说明
  • 1、检测用户是否已登录,未登录不允许上传
  • 2、检测是否存在了该文档的md5,如果已存在,则根据md5查询存储在文档存档表中的数据;如果文档已经在文档存储表中存在,则该文档不需要再获取封面、大小、页码等数据
  • 3、检测文档格式是否符合要求。
  • 4、计算文档md5,然后根据md5再比对一次文档是否在存档表中存在
  • 5、文档未存在,则将文档数据录入文档存储表(document_store)
  • 6、执行文档转pdf,并获取文档页数、封面、摘要等
  • 7、获取文档大小

注意后台可设置上传文档得多少金币,当设置为0时,但是发现 models/Utils.go line56 会判断一个用户上传的文档获得多少分,如果不大于0 则不会进行反转文档格式,因此需要将 line32 score初始化为-1, line56行 判断 如果分数为-1则不进行转换
由于main.go引用的都是github.com的地址,因此需要修改 /root/.go 下的问题才可以生效

调试模式

conf/app.conf 设置为dev模式 表示调试模式

静态模板

应该是在 controllers\HomeControllers\BaseController.go 定义的 layout.html 文件为开始

前后台分离

应该可以在router.go将/admin路径全部注释掉,实现只保留前台功能

关闭评论

在 \views\Home\default\View\svg.html line113 注释掉

{{template "Comment" .}} 

同时 router.go 注释掉 line 58-59

    beego.Router("/comment/:id", &HomeControllers.ViewController{}, "post:Comment")
    beego.Router("/comment/list", &HomeControllers.ViewController{}, "get:GetComment")

删除友情链接

footer.html 的line4~line13

<div class="row wenku-flink">
                <div class="col-xs-12">
                    <div><strong>友情链接</strong></div>
                    <div class="help-block">
                        {{range (Friends)}}
                        <a href="{{.Link}}" target="_blank" title="{{.Title}}">{{.Title}}</a>
                        {{end}}
                    </div>
                </div>
            </div>

后台编辑器

static/Editor/kindeditor/themes/default/default.css
存在编辑器,建议删除

svg添加水印

在models\Utils.go 的 line386添加
//添加文字水印 从配置文件读取水印

helper.SvgTextWatermark(svgfile, beego.AppConfig.String("watermark"), width/6, height/4)

源代码v1.1有这个功能\models\Models.go line585

文字颜色 在 helper\helper.go 文件SvgTextWatermark 函数中进行修改 , 如下代码修改为红色

watermark = append(watermark, fmt.Sprintf(`<text x="%v" y="%v" style="fill:rgba(255,0,0,0.3)" transform="scale(2)">%v</text>`, x, y, text))

模板的设置

模板处理 - beego: 简约 & 强大并存的 Go 应用框架 在controllers\HomeControllers\BaseController.go 定义了this.Layout 其他的controller只需要定义 this.TplName 变量即可 替换 this.Layout 中

不登录直接下载免费文档

在文件 models\UserModel.go 中添加如下方法



func (this *User) CanDownloadFileNoLogin(docId int) (urlStr string, err error) {
    
    
    
    
    if  docId <= 0 {
        err = errParams
        return
    }

    o := orm.NewOrm()
    o.Begin()
    defer func() {
        if err == nil {
            o.Commit()
        } else {
            o.Rollback()
        }
    }()

    
    var docInfo = DocumentInfo{Id: docId}
    if err = o.Read(&docInfo); err != nil {
        helper.Logger.Error(err.Error())
        err = errNotFound
        return
    }

    if docInfo.Price < 0 || docInfo.Price > 0 {
        err = errCannotDown
        return
    }

    doc := &Document{Id: docId}
    if err = o.Read(doc); err != nil {
        helper.Logger.Error(err.Error())
        err = errNotFound
        return
    }

    store := &DocumentStore{Id: docInfo.DsId}
    if err = o.Read(store); err != nil {
        helper.Logger.Error(err.Error())
        err = errNotFound
        return
    }


    docInfo.Dcnt += 1
    if _, err = o.Update(&docInfo); err != nil {
        return
    }

    var cs *CloudStore
    cs, err = NewCloudStore(true)
    if err != nil {
        helper.Logger.Error(err.Error())
        err = errFailedToDown
        return
    }

    object := store.Md5 + "." + strings.TrimLeft(store.Ext, ".")
    urlStr = cs.GetSignURL(object)

    return
}

controllers\HomeControllers\ViewController.go 修改Download 和DownFree


func (this *ViewController) Download() {
    id, _ := this.GetInt(":id")
    if id <= 0 {
        this.ResponseJson(false, "文档id不正确")
    }

    if this.IsLogin == 0 {
        
        link, err := models.NewUser().CanDownloadFileNoLogin(id)
        if err != nil {
            this.ResponseJson(false, err.Error())
        }
        this.ResponseJson(true, "下载链接获取成功", map[string]interface{}{"url": link})
        
    }else {
        link, err := models.NewUser().CanDownloadFile(this.IsLogin, id)
        if err != nil {
            this.ResponseJson(false, err.Error())
        }
        this.ResponseJson(true, "下载链接获取成功", map[string]interface{}{"url": link})
    }

    
}

func (this *ViewController) DownFree() {
    if this.IsLogin > 0 {
        did, _ := this.GetInt("id")
        if free := models.NewFreeDown().IsFreeDown(this.IsLogin, did); free {
            this.ResponseJson(true, fmt.Sprintf("您上次下载过当前文档,且仍在免费下载有效期(%v天)内,本次下载免费", this.Sys.FreeDay))
        }
    }else{
        
        id, _ := this.GetInt(":id")
        if id < 1 {
            this.ResponseJson(false, "文档不存在")
        }
        doc, err := models.NewDocument().GetById(id)

        
        if err != nil || doc.Id <= 0 || doc.Status < models.DocStatusConverting {
            this.ResponseJson(false, "文档不存在")
        }
        if doc.Price == 0 {
            
            this.ResponseJson(true, "免费文档可以直接下载")
        }
    }
    
    this.ResponseJson(false, "不能免费下载,不在免费下载期限内")
}

pdf 添加水印

controllers\HomeControllers\UploadController.go


func (this *UploadController) Post() {
    var (
        ext  string 
        dir  = fmt.Sprintf("./uploads/%v/%v", time.Now().Format("2006/01/02"), this.IsLogin)
        form models.FormUpload
        err  error
    )

    if this.IsLogin == 0 {
        this.ResponseJson(false, "您当前未登录,请先登录")
    }

    this.ParseForm(&form)

    
    f, fh, err := this.GetFile("File")
    if err == nil {
        defer f.Close()
        os.MkdirAll(dir, os.ModePerm)
        ext = strings.ToLower(filepath.Ext(fh.Filename))
        if _, ok := helper.AllowedUploadDocsExt[ext]; !ok {
            this.ResponseJson(false, "您上传的文档格式不正确,请上传正确格式的文档")
        }
        file := fmt.Sprintf("%v-%v-%v", this.IsLogin, time.Now().UnixNano(), ext)
        form.TmpFile = filepath.Join(dir, file)
        form.Ext = ext
        err = this.SaveToFile("File", form.TmpFile)
        

        if err != nil {
            helper.Logger.Error(err.Error())
            this.ResponseJson(false, "文件保存失败")
        } else{
            waterfile := fmt.Sprintf("%v-%v-w-%v", this.IsLogin, time.Now().UnixNano(), ext)    
            outputFile := filepath.Join(dir, waterfile)

            
            args := []string{ form.TmpFile, "stamp", "/root/tools/DocHub/water.pdf","output", outputFile}
            cmd := exec.Command("pdftk", args...)
            
            time.AfterFunc(30*time.Second, func() {
                if cmd.Process != nil {
                    cmd.Process.Kill()
                }
            })

            err = cmd.Run()
            if err == nil {
                os.Remove(form.TmpFile)
                form.TmpFile = outputFile  
            }
        }
    }

    
    err = models.DocumentProcess(this.IsLogin, form)
    if err != nil {
        this.ResponseJson(false, err.Error())
    }
    this.ResponseJson(true, "恭喜您,文档上传成功")
}

制作water文件

from PyPDF2 import PdfFileReader, PdfFileWriter
from reportlab.lib.units import cm
from reportlab.pdfgen import canvas
 
 
def create_watermark(content):
    """水印信息"""
    
    file_name = "mark.pdf"
    c = canvas.Canvas(file_name, pagesize=(21 * cm, 29.7 * cm))
    
    c.translate(5 * cm, 10 * cm)
 
    
    c.setFont("Helvetica", 80)
    
    c.setStrokeColorRGB(0, 1, 0)
    
    c.setFillColorRGB(1, 0, 0)
    
    
    
    c.rotate(30)
    
    c.setFillColorRGB(1, 0, 0, 0.3)
    
    
    
    c.drawString(3 * cm, 0 * cm, content)
    c.setFillAlpha(0.6)
    
    c.save()
    return file_name
 
 
def add_watermark(pdf_file_in, pdf_file_mark, pdf_file_out):
    """把水印添加到pdf中"""
    pdf_output = PdfFileWriter()
    input_stream = open(pdf_file_in, 'rb')
    pdf_input = PdfFileReader(input_stream, strict=False)
 
    
    pageNum = pdf_input.getNumPages()
 
    
    pdf_watermark = PdfFileReader(open(pdf_file_mark, 'rb'), strict=False)
    
    for i in range(pageNum):
        page = pdf_input.getPage(i)
        page.mergePage(pdf_watermark.getPage(0))
        page.compressContentStreams()  
        pdf_output.addPage(page)
    pdf_output.write(open(pdf_file_out, 'wb'))
 
 
if __name__ == '__main__':
    
    
    pdf_file_mark = create_watermark('github5.com')
    

搜索关键词没有URL解码

controllers\HomeControllers\SearchController.go line 115 添加解码 引入包net/url

decodedValue, err := url.QueryUnescape(params["wd"])
        if err != nil {
        } else {
            params["wd"] = decodedValue
        }

批量上传文件

文件上传功能 在 controllers\HomeControllers\UploadController.go 文件的Post方法实现, 该函数主要处理文件信息, 生成FormUpload 结构体(在文件\models\struct.go)

Title, Md5, Intro, Tags, Ext, Filename string
    Chanel, Pid, Cid, Exist, Size, Price   int
    TmpFile                                string 

TmpFile 
Filename 
Title   
Tags 
Intro 
Ext 
Price 
Chanel 
Pid  
Cid 




  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin