Przeglądaj źródła

实现导出pdf

Minho 8 lat temu
rodzic
commit
9c99e8ea3d

+ 5 - 1
conf/app.conf.example

@@ -60,4 +60,8 @@ smtp_port=25
 #发送邮件的显示名称
 [email protected]
 #邮件有效期30分钟
-mail_expired=30
+mail_expired=30
+
+
+###############配置PDF生成工具地址###################
+wkhtmltopdf=D:/Program Files/wkhtmltopdf/bin/wkhtmltopdf.exe

+ 101 - 0
controllers/document.go

@@ -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;
+				}
+			}
+		}
+	}
+}
 
 
 

+ 4 - 4
main.go

@@ -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()
 }
 

+ 6 - 0
models/document.go

@@ -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
+}
 
 
 

+ 0 - 12
models/document_tree.go

@@ -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"`

+ 1 - 0
routers/router.go

@@ -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")
 

BIN
static/pdf-fonts/msyh.ttc


BIN
static/pdf-fonts/msyh.ttf


BIN
static/pdf-fonts/msyhbd.ttc


BIN
static/pdf-fonts/msyhbold.ttf


BIN
static/pdf-fonts/msyhl.ttc


+ 4 - 4
utils/pager.go

@@ -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

+ 0 - 22
utils/pdf.go

@@ -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
-}

+ 77 - 0
utils/pdf_windows.go

@@ -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
+
+}

+ 2 - 2
views/book/index.tpl

@@ -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>

+ 45 - 0
views/document/export.tpl

@@ -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>