实现导出pdf

pull/39/head
Minho 2017-05-06 16:16:27 +08:00
parent a438b8104d
commit 9c99e8ea3d
16 changed files with 250 additions and 50 deletions

View File

@ -61,3 +61,7 @@ smtp_port=25
form_user_name=admin@iminho.me
#邮件有效期30分钟
mail_expired=30
###############配置PDF生成工具地址###################
wkhtmltopdf=D:/Program Files/wkhtmltopdf/bin/wkhtmltopdf.exe

View File

@ -10,11 +10,13 @@ import (
"path/filepath"
"encoding/json"
"html/template"
"container/list"
"github.com/lifei6671/godoc/models"
"github.com/lifei6671/godoc/conf"
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
"github.com/lifei6671/godoc/utils"
)
//DocumentController struct.
@ -558,10 +560,109 @@ func (c *DocumentController) Content() {
c.JsonResult(0,"ok",doc)
}
//导出文件
func (c *DocumentController) Export() {
c.Prepare()
c.TplName = "document/export.tpl"
identify := c.Ctx.Input.Param(":key")
// token := c.GetString("token")
output := c.GetString("output")
//id, _ := c.GetInt(":id")
token := c.GetString("token")
if identify == "" {
c.Abort("404")
}
//如果没有开启你们访问则跳转到登录
if !c.EnableAnonymous && c.Member == nil {
c.Redirect(beego.URLFor("AccountController.Login"),302)
return
}
book := isReadable(identify,token,c)
if book.PrivatelyOwned == 1 {
}
docs, err := models.NewDocument().FindListByBookId(book.BookId)
if err != nil {
beego.Error(err)
c.Abort("500")
}
if output == "pdf" {
dpath := "cache/" + book.Identify
os.MkdirAll(dpath, 0766)
pathList := list.New()
RecursiveFun(0, "", dpath, c, book, docs, pathList)
defer os.RemoveAll(dpath)
os.MkdirAll("./cache", 0766)
pdfpath := "cache/" + identify + ".pdf"
paths := make([]string, len(docs))
index := 0
for e := pathList.Front(); e != nil; e = e.Next() {
paths[index] = e.Value.(string)
index ++
}
beego.Info(paths)
utils.ConverterHtmlToPdf(paths, pdfpath)
c.Ctx.Output.Download(pdfpath, identify + ".pdf")
defer os.Remove(pdfpath)
c.StopRun()
}
c.StopRun()
}
func RecursiveFun(parent_id int,prefix,dpath string,c *DocumentController,book *models.BookResult,docs []*models.Document,paths *list.List) {
for _, item := range docs {
if item.ParentId == parent_id {
name := prefix + strconv.Itoa(item.ParentId) + strconv.Itoa(item.OrderSort) + strconv.Itoa(item.DocumentId)
fpath := dpath + "/" + name + ".html"
paths.PushBack(fpath)
f, err := os.OpenFile(fpath, os.O_CREATE, 0666)
if err != nil {
beego.Error(err)
c.Abort("500")
}
html, err := c.ExecuteViewPathTemplate("document/export.tpl", map[string]interface{}{"Model" : book, "Lists":item,"BaseUrl" : c.BaseUrl()})
if err != nil {
f.Close()
beego.Error(err)
c.Abort("500")
}
f.WriteString(html)
f.Close()
for _, sub := range docs {
if sub.ParentId == item.DocumentId {
RecursiveFun(item.DocumentId,name,dpath,c,book,docs,paths)
break;
}
}
}
}
}

View File

@ -1,18 +1,19 @@
package main
import (
"fmt"
"os"
_ "github.com/go-sql-driver/mysql"
_ "github.com/lifei6671/godoc/routers"
_ "github.com/astaxie/beego/session/redis"
_ "github.com/astaxie/beego/session/memcache"
_ "github.com/astaxie/beego/session/mysql"
"github.com/astaxie/beego"
"github.com/lifei6671/godoc/commands"
"fmt"
"os"
"github.com/lifei6671/godoc/controllers"
"github.com/lifei6671/godoc/conf"
"github.com/lifei6671/godoc/utils"
)
var (
@ -37,7 +38,6 @@ func main() {
beego.ErrorController(&controllers.ErrorController{})
utils.ConverterPdf("a.pdf",nil)
beego.Run()
}

View File

@ -128,7 +128,13 @@ func (m *Document) ReleaseContent(book_id int) {
}
func (m *Document) FindListByBookId(book_id int) (docs []*Document,err error) {
o := orm.NewOrm()
_,err = o.QueryTable(m.TableNameWithPrefix()).Filter("book_id",book_id).All(&docs)
return
}

View File

@ -100,19 +100,7 @@ func getDocumentTree(array []*DocumentTree,parent_id int,selected_id int,selecte
pid = p
}
if pid == parent_id {
/**
$selected = $item['doc_id'] == $selected_id ? ' class="jstree-clicked"' : '';
$selected_li = $item['doc_id'] == $selected_parent_id ? ' class="jstree-open"' : '';
$menu .= '<li id="'.$item['doc_id'].'"'.$selected_li.'><a href="'. route('document.show',['doc_id'=> $item['doc_id']]) .'" title="' . htmlspecialchars($item['doc_name']) . '"'.$selected.'>' . $item['doc_name'] .'</a>';
$key = array_search($item['doc_id'], array_column($array, 'parent_id'));
if ($key !== false) {
self::createTree($item['doc_id'], $array,$selected_id,$selected_parent_id);
}
$menu .= '</li>';
*/
selected := ""
if item.DocumentId == selected_id {
selected = ` class="jstree-clicked"`

View File

@ -58,6 +58,7 @@ func init() {
beego.Router("/docs/:key", &controllers.DocumentController{},"*:Index")
beego.Router("/docs/:key/:id", &controllers.DocumentController{},"*:Read")
beego.Router("/export/:key", &controllers.DocumentController{},"*:Export")
beego.Router("/attach_files/:key/:attach_id",&controllers.DocumentController{},"get:DownloadAttachment")

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -287,16 +287,16 @@ func getFooter(po *PageOptions, totalpages int) string {
*/
func setDefault(po *PageOptions, totalpages int) *PageOptions {
if len(po.FirstPageText) <= 0 {
po.FirstPageText = "首页"
po.FirstPageText = "&laquo;"
}
if len(po.LastPageText) <= 0 {
po.LastPageText = "尾页"
po.LastPageText = "&raquo;"
}
if len(po.PrePageText) <= 0 {
po.PrePageText = "上一页"
po.PrePageText = "&lsaquo;"
}
if len(po.NextPageText) <= 0 {
po.NextPageText = "下一页"
po.NextPageText = "&rsaquo;"
}
if po.CurrentPage >= totalpages {
po.CurrentPage = totalpages

View File

@ -1,22 +0,0 @@
package utils
import (
"github.com/jung-kurt/gofpdf"
"github.com/astaxie/beego"
)
func ConverterPdf(output string,htmlList map[string]string) error {
pdf := gofpdf.New("P", "mm", "A4", "./static/pdf-fonts/msyh.ttf")
pdf.AddPage()
pdf.SetFont("微软雅黑","B",14)
pdf.Cell(40, 10, "Hello, world")
err := pdf.OutputFileAndClose("hello.pdf")
if err != nil {
beego.Error(err)
return err
}
return nil
}

View File

@ -0,0 +1,77 @@
package utils
import (
"os/exec"
"fmt"
"bufio"
"github.com/axgle/mahonia"
"io"
"io/ioutil"
"github.com/astaxie/beego"
)
// 中文说明http://www.jianshu.com/p/4d65857ffe5e#
func ConverterHtmlToPdf(uri []string,path string) {
exe := beego.AppConfig.String("wkhtmltopdf")
if exe == "" {
panic("wkhtmltopdf not exist.")
}
params := []string{"/C",exe,"--margin-bottom","25"}
params = append(params,uri...)
params = append(params,path)
cmd := exec.Command("cmd",params...)
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Println("StdoutPipe: " + err.Error())
return
}
stderr, err := cmd.StderrPipe()
if err != nil {
fmt.Println("StderrPipe: ", err.Error())
return
}
if err := cmd.Start(); err != nil {
fmt.Println("Start: ", err.Error())
return
}
reader := bufio.NewReader(stdout)
enc := mahonia.NewDecoder("gbk")
//实时循环读取输出流中的一行内容
for {
line ,err2 := reader.ReadString('\n')
if err2 != nil || io.EOF == err2 {
break
}
beego.Error(enc.ConvertString(line))
}
bytesErr, err := ioutil.ReadAll(stderr)
if err == nil {
beego.Error(enc.ConvertString(string(bytesErr)))
}else{
beego.Error("Error: Stderr => " + err.Error())
}
if err := cmd.Wait(); err != nil {
beego.Error("Error: ", err.Error())
return
}
return
}

View File

@ -58,9 +58,9 @@
</a>
</div>
<div class="pull-right">
<a :href="'{{urlfor "DocumentController.Index" ":key" ""}}' + item.identify" title="查看文档" data-toggle="tooltip"><i class="fa fa-eye"></i> 查看文档</a>
<a :href="'{{urlfor "DocumentController.Index" ":key" ""}}' + item.identify" title="查看文档" data-toggle="tooltip" target="_blank"><i class="fa fa-eye"></i> 查看文档</a>
<template v-if="item.role_id != 3">
<a :href="'/api/' + item.identify + '/edit'" title="编辑文档" data-toggle="tooltip"><i class="fa fa-edit" aria-hidden="true"></i> 编辑文档</a>
<a :href="'/api/' + item.identify + '/edit'" title="编辑文档" data-toggle="tooltip" target="_blank"><i class="fa fa-edit" aria-hidden="true"></i> 编辑文档</a>
</template>
</div>
<div class="clearfix"></div>

View File

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{.Model.BookName}} - Powered by MinDoc</title>
<!-- Bootstrap -->
<link href="{{.BaseUrl}}/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="{{.BaseUrl}}/static/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<link href="{{.BaseUrl}}/static/jstree/3.3.4/themes/default/style.min.css" rel="stylesheet">
<link href="{{.BaseUrl}}/static/nprogress/nprogress.css" rel="stylesheet">
<link href="{{.BaseUrl}}/static/css/kancloud.css" rel="stylesheet">
<link href="{{.BaseUrl}}/static/css/jstree.css" rel="stylesheet">
{{if eq .Model.Editor "markdown"}}
<link href="{{.BaseUrl}}/static/editor.md/css/editormd.preview.css" rel="stylesheet">
{{else}}
<link href="{{.BaseUrl}}/static/highlight/styles/zenburn.css" rel="stylesheet">
{{end}}
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="{{.BaseUrl}}/static/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="{{.BaseUrl}}/static/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="m-manual manual-reader">
<div class="container-fluid manual-body">
<div class="manual-article">
<div class="article-content">
<h1 id="article-title">{{.Lists.DocumentName}}</h1>
<div class="article-body {{if eq $.Model.Editor "markdown"}}markdown-body editormd-preview-container{{else}}editor-content{{end}}" id="page-content">
{{str2html .Lists.Release}}
</div>
</div>
</div>
</div>
</body>
</html>