-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Validation check issues #14
Comments
👍 |
Validation errors are specific to PDF/A profile. At the moment Prawn doesn't support PDF/A and I personally don't plant to work on it any time soon. I'll be happy to help anyone who decide to contribute PDF/A support. |
Has anyone ever managed to generate a I would be glad if someone could provide a gist or other resources on how to achieve this. Even my co-pilot has been biting his teeth out so far. |
@timokleemann I'm not sure why you are asking this here because in https://github.com/orgs/prawnpdf/discussions/1231#discussioncomment-10982910 you mentioned that you have full ZUGFeRD compatibility which requires PDF/A-3. |
@gettalong Well observed! But I am using GhostScript to convert the Prawn PDFs to |
@timokleemann Ah, okay. Alas, for Prawn itself I can offer you only some guidance. You would need to embed the required PDF/A XMP metadata stream, an ICC color profile (probably SRGB), make sure that you only use embedded fonts and a few other things which Prawn probably already takes care of. It shouldn't be that much of a hassle but one has to do the work, once. You could look at how HexaPDF does it. |
Thanks @gettalong for the guidance. I think I managed to add the required metadata to my PDF using Prawn's info method. Using a tool called mdls I can verify that the metadata is now indeed present in the PDF. My Copilot now suggests that I use the combine_pdf to add the XMP metadata to the file. But do I really need another gem here? Or is there a better way to achieve this? |
No, the combine_pdf is not needed since you just need to attach files to the PDF and this can be done with Prawn itself. |
@gettalong, cool, so I can get along without another gem here. This is a rough idea of my current code:
The problem is that it keeps giving me an error What am I missing here? |
N.b. I haven't had a recent look into the Prawn internals but:
|
Thanks, @gettalong. Below is my updated code.
Unfortunately, I am having trouble referencing the metadata in my code via But, even worse, when I try to render the PDF using
What am I missing here? |
Generally you don't want to use |
@timokleemann this works for me: conformity.rb require 'securerandom'
module Conformity
BASE_DIR = File.join(File.expand_path(File.dirname(__FILE__)))
XMP_DATE_FORMAT = '%Y-%m-%dT%H:%M:%S%:z'
def render(*args, **kwargs)
add_output_intent
add_trailer_data
add_xmp_metadata
super
end
def document
@document ||= Prawn::Document.new({ info: info_data })
end
def create_date
@create_date ||= Time.now
end
def modification_date
@modification_date ||= Time.now
end
def info_data
{}.tap do |data|
info[:Title] = "A title"
info[:Author] = "An author"
info[:Subject] = "A subject"
info[:Keywords] = "Some keywords"
info[:Creator] = "Prawn"
info[:Producer] = "Prawn"
info[:CreationDate] = create_date
info[:ModDate] = modification_date
end
end
def add_trailer_data
# See: https://stackoverflow.com/questions/20085899/what-is-the-id-field-in-a-pdf-file
# The value of the ID entry is not a string but instead an array of two strings.
# And the string values are not arbitrary but instead unique values recommended to be obtained by hashing.
# Thus they especially must not be re-used for different documents
# Added with https://github.com/prawnpdf/pdf-core/pull/16
state.trailer[:ID] = [
# not sure if ByteString is needed here...
PDF::Core::ByteString.new("myDocument"),
PDF::Core::ByteString.new(SecureRandom.uuid)
]
end
def add_output_intent
icc_profile_path = File.join(BASE_DIR, 'colorprofiles', 'sRGB2014.icc')
icc_profile_ref = ref!({ N: 3 })
icc_profile_ref << IO.binread(icc_profile_path)
output_intent = {
S: :GTS_PDFA1,
OutputConditionIdentifier: "sRGB2014.icc",
Info: "sRGB2014.icc",
DestOutputProfile: icc_profile_ref
}
root = state.store.root
root.data[:OutputIntents] = [output_intent]
end
def add_xmp_metadata
xmp_metadata = ref!(Type: :Metadata, Subtype: :XML)
xmp_metadata << xmp
root = state.store.root
root.data[:Metadata] = xmp_metadata
end
def xmp
# NOTE: `begin="w"` should be `begin="\u{FEFF}"` but this crashes VeraPDF....
<<~XMP
<?xpacket begin="w" id="#{SecureRandom.uuid.tr('-', '')}"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
xmlns:pdf="http://ns.adobe.com/pdf/1.3/"
xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/">
<dc:title>
<rdf:Alt>
<rdf:li xml:lang="x-default">A title</rdf:li>
</rdf:Alt>
</dc:title>
<dc:creator>
<rdf:Seq>
<rdf:li>An author</rdf:li>
</rdf:Seq>
</dc:creator>
<dc:subject>
<rdf:Bag>
<rdf:li>A subject</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang="x-default">Some keywords</rdf:li>
</rdf:Alt>
</dc:description>
<xmp:CreatorTool>Prawn</xmp:CreatorTool>
<xmp:CreateDate>#{create_date.strftime(XMP_DATE_FORMAT)}</xmp:CreateDate>
<xmp:ModifyDate>#{modification_date.strftime(XMP_DATE_FORMAT)}</xmp:ModifyDate>
<pdf:Producer>Prawn</pdf:Producer>
<pdfaid:part>3</pdfaid:part>
<pdfaid:conformance>B</pdfaid:conformance>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="r"?>
XMP
end
end pdf_document.rb class PdfDocument
include Prawn::View
prepend Conformity
....
end main.rb #!/usr/bin/env ruby
File.open('output.pdf', 'wb') { |f| f.puts(PdfDocument.new.render) } To validate I used: verapdf --format html -f 3b output.pdf > report.html |
@timokleemann please see #62 to correct my example above use:
def add_xmp_metadata
xmp_metadata = ref!(Type: :Metadata, Subtype: :XML)
xmp_metadata << xmp.force_encoding('BINARY')
# .... omitted
end
def xmp
<<~XMP
<?xpacket begin="\u{FEFF}" id="#{SecureRandom.uuid.tr('-', '')}"?>
# .... omitted
XMP
end |
Hi @sled , this looks good—thank you! There aren't many examples like this available online, so your post will be appreciated by many. |
Hey Guys,
I'm very happy to use prawn 👍
One small thing I got today is that my generated pdf has some validation issues:
So I use latest version of prawn:
In rails console:
Then I also uploaded generated "metadata.pdf" file to http://www.pdf-tools.com/pdf/validate-pdfa-online.aspx
and got some issues in results:
Maybe someone is experienced with same issue and know how to fix it.
Thanks for any help 🍻
The text was updated successfully, but these errors were encountered: