admin管理员组文章数量:1186088
I'm developing a Lua script to generate a multi-page PDF file containing tabular data. My script generates the PDF correctly and the logs show that all the pages are created correctly. However, when I open the PDF file, one of the pages (page 2) is not displayed. The content goes directly from page 1 to page 3.
What I tried: Checked the script logs: everything indicates that page 2 has been generated and included. Validated the structure of PDF objects in the file: all objects (pages, references, xref) seem to be in place. Checked cross-reference structure (xref) and /Kids entries for page tree.
local function creerPDF(fichierPDF, data)
local fichier = assert(io.open(fichierPDF, "w"))
fichier:write("%PDF-1.4\n")
local pages = {}
local kids = {}
local positionY = 700
local lignesParPage = 30
local function nouvellePage()
local pageObj = #pages * 2 + 3
local contentObj = pageObj + 1
table.insert(kids, pageObj .. " 0 R")
table.insert(pages, {page = pageObj, content = contentObj, stream = ""})
positionY = 700
end
local function ajouterEnTete(page)
local header = "q\n"
header = header .. "BT /F1 12 Tf 20 820 Td (Programmeur : LumiArt-Studio) Tj ET\n"
header = header .. "BT /F1 12 Tf 20 800 Td (Date : " .. os.date("%d/%m/%Y %H:%M") .. ") Tj ET\n"
header = header .. "BT /F1 12 Tf 20 780 Td (Machine : TestMachine) Tj ET\n"
header = header .. "BT /F1 12 Tf 50 720 Td (ID) Tj ET\n"
header = header .. "BT /F1 12 Tf 150 720 Td (Type) Tj ET\n"
header = header .. "BT /F1 12 Tf 250 720 Td (Name) Tj ET\n"
header = header .. "BT /F1 12 Tf 350 720 Td (FixtureType) Tj ET\n"
header = header .. "BT /F1 12 Tf 450 720 Td (U.Addrs) Tj ET\n"
header = header .. "Q\n"
page.stream = page.stream .. header
end
local function ajouterDonnee(page, ligne)
local columnPositions = {50, 150, 250, 350, 450}
local values = {ligne.id, ligne.idtype, ligne.name, ligne.fixturetype, ligne.uaddrs}
for i, value in ipairs(values) do
page.stream = page.stream .. string.format("BT /F1 10 Tf %d %d Td (%s) Tj ET\n", columnPositions[i], positionY, tostring(value))
end
positionY = positionY - 20
if positionY < 100 then
nouvellePage()
ajouterEnTete(pages[#pages])
end
end
local function ajouterPiedDePage(page, index, total)
local footer = string.format("BT /F1 10 Tf 500 20 Td (Page %d sur %d) Tj ET\n", index, total)
page.stream = page.stream .. footer
end
nouvellePage()
ajouterEnTete(pages[#pages])
for _, ligne in ipairs(data) do
ajouterDonnee(pages[#pages], ligne)
end
local totalPages = #pages
for i, page in ipairs(pages) do
ajouterPiedDePage(page, i, totalPages)
end
for _, page in ipairs(pages) do
fichier:write(string.format("%d 0 obj\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Resources << /Font << /F1 5 0 R >> >> /Contents %d 0 R >>\nendobj\n", page.page, page.content))
fichier:write(string.format("%d 0 obj\n<< /Length %d >>\nstream\n%s\nendstream\nendobj\n", page.content, #page.stream, page.stream))
end
fichier:write("2 0 obj\n<< /Type /Pages /Kids [")
for _, kid in ipairs(kids) do
fichier:write(kid .. " ")
end
fichier:write(string.format("] /Count %d >>\nendobj\n", #kids))
fichier:write("1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n")
fichier:write("5 0 obj\n<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>\nendobj\n")
local xrefStart = fichier:seek()
fichier:write("xref\n0 " .. (#kids * 2 + 6) .. "\n0000000000 65535 f \n")
local offset = 9
for i = 1, (#kids * 2 + 4) do
fichier:write(string.format("%010d 00000 n \n", offset))
offset = fichier:seek()
end
fichier:write(string.format("trailer\n<< /Size %d /Root 1 0 R >>\nstartxref\n%d\n%%EOF\n", (#kids * 2 + 6), xrefStart))
fichier:close()
end
local data = {} for i = 1, 200 do table.insert(data, {id = i, idtype = "Fixture", name = "Fixture " .. i, fixturetype = "Type " .. i, uaddrs = tostring(i * 100)}) end
creerPDF("output_debug_fixed.pdf", data)
I'm developing a Lua script to generate a multi-page PDF file containing tabular data. My script generates the PDF correctly and the logs show that all the pages are created correctly. However, when I open the PDF file, one of the pages (page 2) is not displayed. The content goes directly from page 1 to page 3.
What I tried: Checked the script logs: everything indicates that page 2 has been generated and included. Validated the structure of PDF objects in the file: all objects (pages, references, xref) seem to be in place. Checked cross-reference structure (xref) and /Kids entries for page tree.
local function creerPDF(fichierPDF, data)
local fichier = assert(io.open(fichierPDF, "w"))
fichier:write("%PDF-1.4\n")
local pages = {}
local kids = {}
local positionY = 700
local lignesParPage = 30
local function nouvellePage()
local pageObj = #pages * 2 + 3
local contentObj = pageObj + 1
table.insert(kids, pageObj .. " 0 R")
table.insert(pages, {page = pageObj, content = contentObj, stream = ""})
positionY = 700
end
local function ajouterEnTete(page)
local header = "q\n"
header = header .. "BT /F1 12 Tf 20 820 Td (Programmeur : LumiArt-Studio) Tj ET\n"
header = header .. "BT /F1 12 Tf 20 800 Td (Date : " .. os.date("%d/%m/%Y %H:%M") .. ") Tj ET\n"
header = header .. "BT /F1 12 Tf 20 780 Td (Machine : TestMachine) Tj ET\n"
header = header .. "BT /F1 12 Tf 50 720 Td (ID) Tj ET\n"
header = header .. "BT /F1 12 Tf 150 720 Td (Type) Tj ET\n"
header = header .. "BT /F1 12 Tf 250 720 Td (Name) Tj ET\n"
header = header .. "BT /F1 12 Tf 350 720 Td (FixtureType) Tj ET\n"
header = header .. "BT /F1 12 Tf 450 720 Td (U.Addrs) Tj ET\n"
header = header .. "Q\n"
page.stream = page.stream .. header
end
local function ajouterDonnee(page, ligne)
local columnPositions = {50, 150, 250, 350, 450}
local values = {ligne.id, ligne.idtype, ligne.name, ligne.fixturetype, ligne.uaddrs}
for i, value in ipairs(values) do
page.stream = page.stream .. string.format("BT /F1 10 Tf %d %d Td (%s) Tj ET\n", columnPositions[i], positionY, tostring(value))
end
positionY = positionY - 20
if positionY < 100 then
nouvellePage()
ajouterEnTete(pages[#pages])
end
end
local function ajouterPiedDePage(page, index, total)
local footer = string.format("BT /F1 10 Tf 500 20 Td (Page %d sur %d) Tj ET\n", index, total)
page.stream = page.stream .. footer
end
nouvellePage()
ajouterEnTete(pages[#pages])
for _, ligne in ipairs(data) do
ajouterDonnee(pages[#pages], ligne)
end
local totalPages = #pages
for i, page in ipairs(pages) do
ajouterPiedDePage(page, i, totalPages)
end
for _, page in ipairs(pages) do
fichier:write(string.format("%d 0 obj\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Resources << /Font << /F1 5 0 R >> >> /Contents %d 0 R >>\nendobj\n", page.page, page.content))
fichier:write(string.format("%d 0 obj\n<< /Length %d >>\nstream\n%s\nendstream\nendobj\n", page.content, #page.stream, page.stream))
end
fichier:write("2 0 obj\n<< /Type /Pages /Kids [")
for _, kid in ipairs(kids) do
fichier:write(kid .. " ")
end
fichier:write(string.format("] /Count %d >>\nendobj\n", #kids))
fichier:write("1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n")
fichier:write("5 0 obj\n<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>\nendobj\n")
local xrefStart = fichier:seek()
fichier:write("xref\n0 " .. (#kids * 2 + 6) .. "\n0000000000 65535 f \n")
local offset = 9
for i = 1, (#kids * 2 + 4) do
fichier:write(string.format("%010d 00000 n \n", offset))
offset = fichier:seek()
end
fichier:write(string.format("trailer\n<< /Size %d /Root 1 0 R >>\nstartxref\n%d\n%%EOF\n", (#kids * 2 + 6), xrefStart))
fichier:close()
end
local data = {} for i = 1, 200 do table.insert(data, {id = i, idtype = "Fixture", name = "Fixture " .. i, fixturetype = "Type " .. i, uaddrs = tostring(i * 100)}) end
creerPDF("output_debug_fixed.pdf", data)
Share Improve this question asked Jan 25 at 17:42 JoshJosh 611 silver badge4 bronze badges New contributor Josh is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct. 1- 1 Yet again without your example it is almost impossible to guess which byte is wrong (only need one binary bit in the wrong position to corrupt a PDF). Try this one as text it has 3 pages all the same. easyupload.io/40jh21 – K J Commented Jan 25 at 21:16
1 Answer
Reset to default 1The Problem with thinking in terms of content flow is that a PDF cannot be written like one HTML page.
A PDF is defined as a number of page medias either before or after first parse and thus before any second pass needed to use those numbers.
We can decide that if there are 30 lines per page and we know we need to write 75 entries, then we will need to prepare 3 pages. It does not matter if blank or the same content or different content we MUST either know OR replace any estimate later (by total rewrite the catalogue of objects).
Let use presume 3 the same from one page header style. Then we know at the start we only need to count for page 0, 1 & 2 (ALL PDF writers internally start with Page 0 which a PDF Viewer will later display as Page 1).
%PDF-1.4
1 0 obj <</Type/Catalog/Pages 2 0 R>> endobj
2 0 obj <</Type/Pages/Count 3/Kids[4 0 R 5 0 R 6 0 R ]>> endobj
3 0 obj <</Type/Font/Subtype/Type1/BaseFont/Helvetica>> endobj
4 0 obj <</Type/Page/Parent 2 0 R/MediaBox[0 0 595 842]/Resources<</Font<</F0 3 0 R>>>>/Contents 7 0 R>> endobj
5 0 obj <</Type/Page/Parent 2 0 R/MediaBox[0 0 595 842]/Resources<</Font<</F0 3 0 R>>>>/Contents 7 0 R>> endobj
6 0 obj <</Type/Page/Parent 2 0 R/MediaBox[0 0 595 842]/Resources<</Font<</F0 3 0 R>>>>/Contents 7 0 R>> endobj
7 0 obj <</Length 8 0 R>>
stream
q 0 g
BT /F0 12 Tf 1 0 0 1 20 820 Tm (Programmeur : LumiArt-Studio) Tj ET
1 0 0 1 20 800 cm BT (Date : " .. os.date \("%d/%m/%Y %H:%M"\) .. ") Tj ET
1 0 0 1 0 -20 cm BT (Machine : Test Machine) Tj ET
1 0 0 1 30 -100 cm BT (ID :) Tj ET
1 0 0 1 100 0 cm BT (Type :) Tj ET
1 0 0 1 100 0 cm BT (Name :) Tj ET
1 0 0 1 100 0 cm BT (Fixture Type :) Tj ET
1 0 0 1 100 0 cm BT (U.Address :) Tj ET
Q
endstream
endobj
8 0 obj 0548 endobj
xref
0 9
0000000000 65536 f
0000000009 00000 n
0000000054 00000 n
0000000118 00000 n
0000000181 00000 n
0000000293 00000 n
0000000405 00000 n
0000000517 00000 n
0000000957 00000 n
trailer
<</Size 9/Root 1 0 R>>
startxref
977
%%EOF
If you need each page to show different entries like a page number of different font text and or images. Then you need a fresh object for each page and possibly their resources if different.
If you need to write the pages last we can append a replacement line for the first estimated one. This is usually done either as an incremental addition or allowed for in build by index the "only" entry with a higher address in the Xref index.
thus a late object 2 entry could be like this
2 0 obj <</Type/Pages/Count 4/Kids[4 0 R 5 0 R 6 0 R 13 0 R]>> endobj
xref
0 15
0000000000 65536 f
0000000009 00000 n
0000025168 00000 n
0000000054 00000 n
本文标签: Problem with a missing page when generating a PDF in LuaStack Overflow
版权声明:本文标题:Problem with a missing page when generating a PDF in Lua - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738348875a2078589.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论