Closed mthizozo closed 5 years ago
Can you verify that the font used locally is exactly the same as the one used in openshift?
yes I used. pdf.setFont("arial" , "B", 13). This is the same code thats deployed yet locally it gives no error
Can you verify that the JSON files in the font subdirectory are that same in both the remote and local locations? In your case, it looks like font/helveticab.json may be problematic.
@jung-kurt we've experienced the same problem when deploying to heroku. Everything works in local too. Maybe getting the wrong path for the fonts? In heroku source code goes to the app
directory
Thanks, @mapreal19 -- your information will be helpful in correcting this problem.
Found our problem. What happened is that we had an error when trying to render an image. That's why f.err
wasn't nil here: https://github.com/jung-kurt/gofpdf/blob/master/fpdf.go#L1954-L1956 and made us think there was an issue in our fonts.
I think instead of returning we should panic
here? SetFont
should succeed otherwise we will have problems like this, assuming the font was set when actually it wasn't because of a previous error.
Thank you for tracking this down, @mapreal19.
One can argue with the way gofpdf handles errors, but given the large number of steps that go into creating a document, embedding the error (one of the patterns shown in Errors are values) relieves the programmer of checking for an error condition at every turn. Rather than introduce panics into the codebase, I'd like to pinpoint where the embedded error scheme failed in this case. Somewhere I think the internal error value got overwritten or a method failed to execute a quick return on an error condition. In this case, the final error check when OutputFileAndClose()
or friend is called should have clearly indicated that it was an image rendering error.
@mapreal19, can you identify the minimal number of steps needed to reproduce the problem? Will an attempt to load a non-existent image followed by a call to SetFont()
result in the crash? I will step through with Delve to see where the error handling is going astray.
Just calling this I think would do (let me know if you're able to reproduce):
var pdf = gofpdf.New("P", "pt", "A4", "")
pdf.AddPage()
// set imgPath to a non-existing path
pdf.ImageOptions(imgPath, margin, margin, imgSz, imgSz, false, opt, 0, "")
pdf.SetFont(titleFont, "B", titleSz)
I suspect the error is being set here: https://github.com/jung-kurt/gofpdf/blob/master/fpdf.go#L3090
And yeah thanks for the explanation, panic
there wasn't a great idea given the way you handle errors. It was meant for a quick patch. Hope you guys can find where that overwrite is being done.
Thanks, @mapreal19 -- this is helpful.
I am not able to reproduce the problem with the following snippet. However, I am not able to test it on openshift or heroku where the problems have been reported.
package main
import (
"fmt"
"os"
"github.com/jung-kurt/gofpdf/v2"
)
func main() {
var pdf = gofpdf.New("P", "pt", "A4", "")
pdf.AddPage()
pdf.ImageOptions("foo.jpg", 10, 10, 100, 100, false, gofpdf.ImageOptions{}, 0, "")
pdf.SetFont("helvetica", "", 14)
err := pdf.OutputFileAndClose("foo.pdf")
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
}
}
Locally, this results in the expected error open foo.jpg: no such file or directory
. I do recall some error handling changes were made to some font logic. Can anyone experiencing this problem verify that an up-to-date version of the package is being used?
Hmm I think I missed this line after pdf.SetFont
:
pdf.MultiCell(0, 10, "some-text", "", "", false)
This will have the error here: https://github.com/jung-kurt/gofpdf/blob/f92bdc0bcf650f019ee76c1298a4d04c8237cba0/fpdf.go#L2578
@jung-kurt the helveiticab.json files are the same locally and remotely.
Hi @jung-kurt , the code is failing when pdf.multicell is called,
@mapreal19 we are experiencing the exact same issue when using multicell, and its failing on fpdf.go at that same line 2578. what is most strange is that its working fine locally, what would be different after deploying the code?
@mthizozo maybe there is a hidden error like in my case? are you using images?
This commit may be helpful for you: https://github.com/mapreal19/gofpdf/commit/83db124beba3a79b5812070468cce87bfc81c05d
What I did is forking the project and added a bunch of logs until I discovered what was going on
3aaf0b1a66c0ab02d925917376898a5856061d59 (and f58a9cb00082f4f0ee8b2e5c64a6455de46bd659 for version 2) fixes the particular problem with MultiCell()
but I think there may be a larger problem here. I'd like to identify why cloud-based builds fail when local ones do not.
In my case it was because the image path was hardcoded in local, hence it didn't work in heroku so not a problem with gofpdf
. Not sure about the Openshift case
Let's reopen this if it is still a problem with some environments.
On windows 10 pro, it works fine; howerver on linux, it does not.
Error
panic: runtime error: index out of range
goroutine 1 [running]:
github.com/jung-kurt/gofpdf.(*Fpdf).SplitLines(0xc00020c000, 0xc0001dd7d0, 0x10, 0x20, 0x4055800000000000, 0x20, 0x40, 0x0)
/gohome/pkg/mod/github.com/jung-kurt/gofpdf@v1.12.6/fpdf.go:2519 +0x4d4
mysite.com/my_project/smartfactory-server/report.DrawColumnTable(0xc00020c000, 0xc000192960, 0x3, 0x3)
/gohome/src/mysite.com/my_project/smartfactory-server/report/table.go:133 +0x64a
mysite.com/my_project/smartfactory-server/report.(*Report).writeReportCover(0xc00020a000, 0x0, 0x0)
/gohome/src/mysite.com/my_project/smartfactory-server/report/report.go:252 +0xca2
mysite.com/my_project/smartfactory-server/report.(*Report).Start(0xc00020a000, 0x7ffd9b71a779, 0x8)
/gohome/src/mysite.com/my_project/smartfactory-server/report/report.go:188 +0x482
mysite.com/my_project/smartfactory-server/report.(*Server).Start(0xc000173260, 0x9a3822, 0x6)
/gohome/src/mysite.com/my_project/smartfactory-server/report/server.go:116 +0x107
github.com/devplayg/hippo.(*Engine).Start(0xc000192690, 0x0, 0x0)
/gohome/pkg/mod/github.com/devplayg/hippo@v0.0.0-20190916124707-bb4b6afa7a8d/engine.go:39 +0x40
main.main()
/gohome/src/mysite.com/my_project/smartfactory-server/cmd/report/report.go:46 +0x1ea
Code: "DrawColumnTable" function
func DrawTable(pdf *gofpdf.Fpdf, data [][]string) {
resetTable(pdf)
colCount := len(data[0])
colWidth := float64(PDF_WIDTH / colCount)
const (
marginLeft = 15.0
lineHeight = 4.5
cellGap = 2.0
)
type cellType struct {
str string
list [][]byte
ht float64
}
var (
cell cellType
)
pdf.Ln(-1)
startRowNum := 0
header := data[0]
// Headers
pdf.SetX(marginLeft)
pdf.SetTextColor(24, 24, 24)
pdf.SetFillColor(230, 230, 230)
for colJ := 0; colJ < colCount; colJ++ {
pdf.CellFormat(colWidth, 8, header[colJ], "1", 0, "CM", true, 0, "")
}
pdf.Ln(-1)
pdf.SetTextColor(24, 24, 24)
pdf.SetFillColor(255, 255, 255)
startRowNum = 1
// Rows
y := pdf.GetY()
for row := startRowNum; row < len(data); row++ {
maxHt := lineHeight
// Cell height calculation loop
cellList := make([]cellType, 0)
for col := 0; col < colCount; col++ {
cell.str = data[row][col]
cell.list = pdf.SplitLines([]byte(cell.str), colWidth-cellGap-cellGap)
cell.ht = float64(len(cell.list)) * lineHeight
if cell.ht > maxHt {
maxHt = cell.ht
}
cellList = append(cellList, cell)
}
// Cell render loop
x := marginLeft
for colJ := 0; colJ < colCount; colJ++ {
pdf.Rect(x, y, colWidth, maxHt+cellGap+cellGap, "D")
cell = cellList[colJ]
cellY := y + cellGap + (maxHt-cell.ht)/2
for splitJ := 0; splitJ < len(cell.list); splitJ++ {
pdf.SetXY(x+cellGap, cellY)
pdf.CellFormat(colWidth-cellGap-cellGap, lineHeight, string(cell.list[splitJ]), "", 0, "L", false, 0, "")
cellY += lineHeight
}
x += colWidth
}
y += maxHt + cellGap + cellGap
}
pdf.Ln(-1)
}
Input data of [][]string
([][]string) (len=3 cap=3) {
([]string) (len=2 cap=2) {
(string) (len=16) "보고서 이름",
(string) (len=16) "기간 보고서"
},
([]string) (len=2 cap=2) {
(string) (len=13) "대상 기간",
(string) (len=23) "2019-10-04 ~ 2019-10-04"
},
([]string) (len=2 cap=2) {
(string) (len=13) "작성 시간",
(string) (len=25) "2019-10-07T10:15:40+09:00"
}
}
func CreatePdf(fontDir string) *gofpdf.Fpdf {
var fontMap = map[string]string{
HangulFont: "NanumGothic.ttf",
HangulBoldFont: "NanumGothicBold.ttf",
}
pdf := gofpdf.New("P", "mm", "A4", fontDir)
pdf.AddUTF8Font(HangulFont, "", fontMap[HangulFont])
pdf.AddUTF8Font(HangulBoldFont, "B", fontMap[HangulBoldFont])
pdf.AddUTF8Font(HangulFont, "I", fontMap[HangulFont])
pdf.AddUTF8Font(HangulBoldFont, "BI", fontMap[HangulBoldFont])
pdf.SetTopMargin(30)
pdf.SetHeaderFuncMode(func() {
pdf.Image("img/logo_dsme.png", 10, 6, 30, 0, false, "", 0, "")
pdf.SetY(5)
//pdf.SetFont(HangulFont, "", 15)
pdf.SetFont(HangulFont, "", 10)
pdf.Cell(80, 0, "")
pdf.CellFormat(30, 9, "SMART FACTORY REPORT", "0", 0, "C", false, 0, "")
pdf.Ln(20)
}, true)
pdf.SetFooterFunc(func() {
pdf.SetY(-15)
pdf.SetFont(HangulFont, "I", 8)
pdf.CellFormat(0, 10, fmt.Sprintf("Page %d/{nb}", pdf.PageNo()),
"", 0, "C", false, 0, "")
})
pdf.AliasNbPages("")
pdf.SetFont(HangulFont, "", 16)
return pdf
}
Just hit this in my environment:
2019/10/09 03:15:33 http: panic serving 127.0.0.1:42980: runtime error: index out of range
goroutine 720 [running]:
net/http.(*conn).serve.func1(0xc0003426e0)
C:/Go/src/net/http/server.go:1746 +0xd7
panic(0x861700, 0xc4f5c0)
C:/Go/src/runtime/panic.go:513 +0x1c7
github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf.(*utf8FontFile).getSymbols(0xc0003c02a0, 0xadc2, 0xc00038ca10, 0xc0012f8c90, 0xc0012f87e0, 0xc000487400, 0x3b, 0x80, 0xc00047a3c0, 0x0, ...)
E:/Kent/git/go/src/github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf/utf8fontfile.go:793 +0x535
github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf.(*utf8FontFile).getSymbols(0xc0003c02a0, 0x13, 0xc00038ca10, 0xc0012f8c90, 0xc0012f87e0, 0xc00047a3c0, 0x3a, 0x3a, 0xc00038ca10, 0xc0012f8c90, ...)
E:/Kent/git/go/src/github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf/utf8fontfile.go:814 +0x2b2
github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf.(*utf8FontFile).parseSymbols(0xc0003c02a0, 0xc0012f8d20, 0x37, 0xc0012f8780, 0x3ff0000000000000, 0x0, 0x44, 0x4)
E:/Kent/git/go/src/github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf/utf8fontfile.go:563 +0x56b
github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf.(*utf8FontFile).GenerateСutFont(0xc0003c02a0, 0xc0012f8d20, 0x0, 0xc00041c620, 0xe)
E:/Kent/git/go/src/github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf/utf8fontfile.go:672 +0x432
github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf.(*Fpdf).putfonts(0xc00050e000)
E:/Kent/git/go/src/github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf/fpdf.go:4031 +0xb55
github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf.(*Fpdf).putresources(0xc00050e000)
E:/Kent/git/go/src/github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf/fpdf.go:4506 +0x99
github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf.(*Fpdf).enddoc(0xc00050e000)
E:/Kent/git/go/src/github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf/fpdf.go:4693 +0x77
github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf.(*Fpdf).Close(0xc00050e000)
E:/Kent/git/go/src/github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf/fpdf.go:688 +0x9b
github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf.(*Fpdf).Output(0xc00050e000, 0x98ce00, 0xc000164770, 0x0, 0xc00050e800)
E:/Kent/git/go/src/github.com/kent-h/nextslope-backend/vendor/github.com/jung-kurt/gofpdf/fpdf.go:3414 +0xde
github.com/kent-h/nextslope-backend/report/pdf.(*reportGenerator).Complete(0xc0003041e0, 0xc00041c2e0, 0xc, 0xc00041c2f0)
E:/Kent/git/go/src/github.com/kent-h/nextslope-backend/report/pdf/generate.go:145 +0x64
github.com/kent-h/nextslope-backend/report.Generate(0xc000306b80, 0x6, 0x66, 0x8, 0x0, 0x0, 0x1, 0x1, 0x8, 0x0, ...)
E:/Kent/git/go/src/github.com/kent-h/nextslope-backend/report/report.go:131 +0x11d9
github.com/kent-h/nextslope-backend/server.postMaintenanceSignOff(0x991280, 0xc0001760e0, 0xc0003b1000)
E:/Kent/git/go/src/github.com/kent-h/nextslope-backend/server/maintenance_record.go:257 +0x464
net/http.HandlerFunc.ServeHTTP(0x90aee0, 0x991280, 0xc0001760e0, 0xc0003b1000)
C:/Go/src/net/http/server.go:1964 +0x4b
github.com/kent-h/nextslope-backend/vendor/github.com/gorilla/mux.(*Router).ServeHTTP(0xc0000f8cc0, 0x991280, 0xc0001760e0, 0xc0003b1000)
E:/Kent/git/go/src/github.com/kent-h/nextslope-backend/vendor/github.com/gorilla/mux/mux.go:133 +0xf8
net/http.StripPrefix.func1(0x991280, 0xc0001760e0, 0xc0003b0d00)
C:/Go/src/net/http/server.go:2003 +0x192
net/http.HandlerFunc.ServeHTTP(0xc00036bbf0, 0x991280, 0xc0001760e0, 0xc0003b0d00)
C:/Go/src/net/http/server.go:1964 +0x4b
github.com/kent-h/nextslope-backend/vendor/github.com/gorilla/mux.(*Router).ServeHTTP(0xc00037b020, 0x991280, 0xc0001760e0, 0xc0003b0d00)
E:/Kent/git/go/src/github.com/kent-h/nextslope-backend/vendor/github.com/gorilla/mux/mux.go:133 +0xf8
net/http.serverHandler.ServeHTTP(0xc000196a90, 0x991280, 0xc0001760e0, 0xc0003b0b00)
C:/Go/src/net/http/server.go:2741 +0xb2
net/http.(*conn).serve(0xc0003426e0, 0x991540, 0xc000069d80)
C:/Go/src/net/http/server.go:1847 +0x64d
created by net/http.(*Server).Serve
C:/Go/src/net/http/server.go:2851 +0x2fc
The strange part is that it seems to run perfectly fine (generates the pdf without errors) exactly once when the process is started, but fails on every subsequent attempt.
I'm using in-memory fonts (AddUTF8FontFromBytes
), so I currently suspect something is being overwritten where it shouldn't be...
@Kent-H -- This seems to be related to #315. A hacky workaround has been merged that makes a copy of in-memory fonts. I don't see any version information in the panic report but if your version predates eeeab0b32e45c4544d2fe95ad76c07a1bf695aa2 from four days ago you may want to update the gofpdf package(go get -u github.com/jung-kurt/gofpdf
). Can you do this and report back?
Updating appears to have fixed my issue, thank you!
Thanks for the report, @Kent-H.
Hi Jung Kurt
Please assist as i am recieving an index out range error on fpdf.go link 2578 where the font is set after deploying to openshift, yet the code is working locally.
Please advise what if the library would behave differently on different environments