Quellcode durchsuchen

add excel to pdf

animeic vor 2 Jahren
Ursprung
Commit
3ecaf37186
9 geänderte Dateien mit 175 neuen und 7 gelöschten Zeilen
  1. 18 0
      boxcost/api/bill-produce.go
  2. 19 1
      boxcost/api/bill.go
  3. 103 0
      boxcost/api/print.go
  4. 1 0
      boxcost/api/router.go
  5. 22 0
      boxcost/api/utils.go
  6. 1 0
      boxcost/app.yaml
  7. 8 6
      boxcost/conf/app.go
  8. 1 0
      boxcost/go.mod
  9. 2 0
      boxcost/go.sum

+ 18 - 0
boxcost/api/bill-produce.go

@@ -154,6 +154,7 @@ func DelProduceBill(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 
 func DownProduceBill(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 	billId := c.Query("id")
+	isPdf := c.Query("isPdf")
 	if len(billId) < 1 {
 		return nil, fmt.Errorf("id不能为空")
 	}
@@ -189,6 +190,23 @@ func DownProduceBill(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 	//设置对应的数据
 	billExcel.Draws()
 
+	// 下载为pdf
+	if isPdf == "true" {
+		buf, _ := f.WriteToBuffer()
+		res, err := excelToPdf(buf, apictx.Svc.Conf.PdfApiAddr)
+		if err != nil {
+			return nil, errors.New("转化pdf失败")
+		}
+		c.Header("Content-Type", "application/octet-stream")
+		c.Header("Content-Disposition", "attachment; filename="+"bill.pdf")
+		c.Header("Content-Transfer-Encoding", "binary")
+		err = res.Write(c.Writer)
+		if err != nil {
+			return nil, err
+		}
+		return nil, nil
+	}
+
 	c.Header("Content-Type", "application/octet-stream")
 	c.Header("Content-Disposition", "attachment; filename="+"bill.xlsx")
 	c.Header("Content-Transfer-Encoding", "binary")

+ 19 - 1
boxcost/api/bill.go

@@ -122,6 +122,7 @@ func GetBills(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 
 func DownLoadBills(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 	billId := c.Query("id")
+	isPdf := c.Query("isPdf")
 	if len(billId) < 1 {
 		return nil, fmt.Errorf("id不能为空")
 	}
@@ -158,10 +159,27 @@ func DownLoadBills(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 	//设置对应的数据
 	billExcel.Draws()
 
+	// 下载为pdf
+	if isPdf == "true" {
+		buf, _ := f.WriteToBuffer()
+		res, err := excelToPdf(buf, apictx.Svc.Conf.PdfApiAddr)
+		if err != nil {
+			return nil, errors.New("转化pdf失败")
+		}
+		c.Header("Content-Type", "application/octet-stream")
+		c.Header("Content-Disposition", "attachment; filename="+"bill.pdf")
+		c.Header("Content-Transfer-Encoding", "binary")
+		err = res.Write(c.Writer)
+		if err != nil {
+			return nil, err
+		}
+		return nil, nil
+	}
+
+	// 下载为execl
 	c.Header("Content-Type", "application/octet-stream")
 	c.Header("Content-Disposition", "attachment; filename="+"bill.xlsx")
 	c.Header("Content-Transfer-Encoding", "binary")
-
 	err = f.Write(c.Writer)
 	if err != nil {
 		return nil, err

+ 103 - 0
boxcost/api/print.go

@@ -0,0 +1,103 @@
+package api
+
+import (
+	"fmt"
+	"os"
+	"os/exec"
+	"path"
+	"runtime"
+	"strings"
+	"testing"
+
+	"github.com/gin-gonic/gin"
+)
+
+func Printr(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	return nil, nil
+
+}
+
+func TestToPdf(t *testing.T) {
+
+	fileSrcPath := "/Users/xing/Desktop/123/test2.docx" //自己机器上的文件地址
+	outPath := "/Users/xing/Desktop/123/pdf"            //转出文件的路径
+	fileType := "pdf"
+
+	osName := runtime.GOOS //获取系统类型
+	switch osName {
+	case "darwin": //mac系统
+		command := "/Applications/LibreOffice.app/Contents/MacOS/soffice"
+		pdfFile, err := FuncDocs2Pdf(command, fileSrcPath, outPath, fileType)
+		if err != nil {
+			println("转化异常:", err.Error())
+		}
+		fmt.Println("转化后的文件:", pdfFile)
+	case "linux":
+		command := "libreoffice7.3"
+		pdfFile, err := FuncDocs2Pdf(command, fileSrcPath, outPath, fileType)
+		if err != nil {
+			println("转化异常:", err.Error())
+		}
+		fmt.Println("转化后的文件:", pdfFile)
+	case "windows":
+		command := "soffice libreoffice" // 因为没有windows机器需要自己测试下这个命令行
+		pdfFile, err := FuncDocs2Pdf(command, fileSrcPath, outPath, fileType)
+		if err != nil {
+			println("转化异常:", err.Error())
+		}
+		fmt.Println("转化后的文件:", pdfFile)
+	default:
+		fmt.Println("暂时不支持的系统转化:" + runtime.GOOS)
+	}
+}
+
+/**
+*@tips libreoffice 转换指令:
+* libreoffice6.2 invisible --convert-to pdf csDoc.doc --outdir /home/[转出目录]
+*
+* @function 实现文档类型转换为pdf或html
+* @param command:libreofficed的命令(具体以版本为准);win:soffice; linux:libreoffice6.2
+*     fileSrcPath:转换文件的路径
+*     fileOutDir:转换后文件存储目录
+*     converterType:转换的类型pdf/html
+* @return fileOutPath 转换成功生成的文件的路径 error 转换错误
+ */
+func FuncDocs2Pdf(command string, fileSrcPath string, fileOutDir string, converterType string) (fileOutPath string, error error) {
+	//校验fileSrcPath
+	srcFile, erByOpenSrcFile := os.Open(fileSrcPath)
+	if erByOpenSrcFile != nil && os.IsNotExist(erByOpenSrcFile) {
+		return "", erByOpenSrcFile
+	}
+	//如文件输出目录fileOutDir不存在则自动创建
+	outFileDir, erByOpenFileOutDir := os.Open(fileOutDir)
+	if erByOpenFileOutDir != nil && os.IsNotExist(erByOpenFileOutDir) {
+		erByCreateFileOutDir := os.MkdirAll(fileOutDir, os.ModePerm)
+		if erByCreateFileOutDir != nil {
+			fmt.Println("File ouput dir create error.....", erByCreateFileOutDir.Error())
+			return "", erByCreateFileOutDir
+		}
+	}
+	//关闭流
+	defer func() {
+		_ = srcFile.Close()
+		_ = outFileDir.Close()
+	}()
+	//convert
+	cmd := exec.Command(command, "--invisible", "--language=zh-CN", "--convert-to", converterType,
+		fileSrcPath, "--outdir", fileOutDir)
+	byteByStat, errByCmdStart := cmd.Output()
+	//命令调用转换失败
+	if errByCmdStart != nil {
+		return "", errByCmdStart
+	}
+	//success
+	fileOutPath = fileOutDir + "/" + strings.Split(path.Base(fileSrcPath), ".")[0]
+	if converterType == "html" {
+		fileOutPath += ".html"
+	} else {
+		fileOutPath += ".pdf"
+	}
+	fmt.Println("文件转换成功...", string(byteByStat))
+	return fileOutPath, nil
+}

+ 1 - 0
boxcost/api/router.go

@@ -14,6 +14,7 @@ func RegRouters(svc *Service) {
 
 	//数据存储
 	boxcost.POST("/save/policy", ServiceObsUploadPolicy)
+	boxcost.GET("/printr", Printr)
 
 	// 材料管理
 	Material(boxcost)

+ 22 - 0
boxcost/api/utils.go

@@ -3,8 +3,12 @@ package api
 import (
 	"box-cost/db/model"
 	"box-cost/db/repo"
+	"bytes"
 	"fmt"
+	"net/http"
+	"time"
 
+	"github.com/thecodingmachine/gotenberg-go-client/v7"
 	"go.mongodb.org/mongo-driver/bson"
 	"go.mongodb.org/mongo-driver/bson/primitive"
 )
@@ -57,3 +61,21 @@ func searchBillTypeById(ctx *ApiSession, collectName string, id primitive.Object
 	}
 	return curbill["type"].(string), nil
 }
+
+func excelToPdf(formBody *bytes.Buffer, pdfHost string) (*http.Response, error) {
+	httpClient := &http.Client{
+		Timeout: time.Duration(5) * time.Second,
+	}
+	client := &gotenberg.Client{Hostname: pdfHost, HTTPClient: httpClient}
+	doc, err := gotenberg.NewDocumentFromBytes("foo.xlsx", formBody.Bytes())
+	if err != nil {
+		fmt.Println("fdf:", err)
+		return nil, err
+	}
+
+	req := gotenberg.NewOfficeRequest(doc)
+	req.Landscape(true)
+
+	return client.Post(req)
+
+}

+ 1 - 0
boxcost/app.yaml

@@ -2,6 +2,7 @@ port: 8888
 name: boxcost
 version: 1.0.0
 saveType: obs
+pdfApiAddr: "http://localhost:3000"
 
 obs:
   bucket: sku3d-test

+ 8 - 6
boxcost/conf/app.go

@@ -1,7 +1,6 @@
 package conf
 
 import (
-	"fmt"
 	"os"
 
 	"box-cost/log"
@@ -16,9 +15,10 @@ const (
 )
 
 type AppConf struct {
-	Name     string
-	Version  string
-	SaveType string //obs, oss, minio
+	Name       string
+	Version    string
+	SaveType   string //obs, oss, minio
+	PdfApiAddr string
 
 	Jwt struct {
 		Realm       string
@@ -93,8 +93,10 @@ func NewAppConf(filePath string) (*AppConf, error) {
 	if len(natsHost) > 0 {
 		c.Nats.Url = natsHost
 	}
-	fmt.Println("Env NATS=>", natsHost)
-
+	pdfApiAddr := os.Getenv("PDF_API_ADDR")
+	if len(pdfApiAddr) > 0 {
+		c.PdfApiAddr = pdfApiAddr
+	}
 	AppConfig = c
 	return c, nil
 }

+ 1 - 0
boxcost/go.mod

@@ -61,6 +61,7 @@ require (
 	github.com/spf13/jwalterweatherman v1.1.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/subosito/gotenv v1.2.0 // indirect
+	github.com/thecodingmachine/gotenberg-go-client/v7 v7.2.0
 	github.com/ugorji/go/codec v1.1.7 // indirect
 	github.com/xdg-go/pbkdf2 v1.0.0 // indirect
 	github.com/xdg-go/scram v1.1.2 // indirect

+ 2 - 0
boxcost/go.sum

@@ -1146,6 +1146,8 @@ github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG
 github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
 github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
+github.com/thecodingmachine/gotenberg-go-client/v7 v7.2.0 h1:wsdZLvaHRttyvaji+0zqhDNeVXt4atA1A3XNqDkUTVo=
+github.com/thecodingmachine/gotenberg-go-client/v7 v7.2.0/go.mod h1:ABZ2YPzV+IMgtj91+DkoB8/y3qezCQvWhKnGxkY2cSs=
 github.com/tidwall/gjson v1.9.4 h1:oNis7dk9Rs3dKJNNigXZT1MTOiJeBtpurn+IpCB75MY=
 github.com/tidwall/gjson v1.9.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
 github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=