我正在使用 Python 3.3 并尝试使用精彩的 fgfgen / forge_fdf 脚本(谢谢大家,顺便说一句)。
当我尝试运行 fdfgen 的示例测试时,我返回以下错误。
safe = utf16.replace('\x00)', '\x00\\)').replace('\x00(', '\x00\\(')
TypeError: expected bytes, bytearray or buffer compatible object
环顾一番后,这似乎是 python 3 处理 unicode 编码的结果?但我不确定。这是执行的 fdfgen 代码的示例,随后是很好地提供的 fdfgen 代码。提前致谢:
>>> from fdfgen import forge_fdf
>>> fields = [('last_name', u'Spencer')]
>>> fdf = forge_fdf('SMBRPython.pdf', fields, [], [], [])
# -*- coding: utf-8 -*-
"""
Port of the PHP forge_fdf library by Sid Steward
(http://www.pdfhacks.com/forge_fdf/)
Anders Pearson <anders@columbia.edu> at Columbia Center For New Media Teaching
and Learning <http://ccnmtl.columbia.edu/>
"""
__author__ = "Anders Pearson <anders@columbia.edu>"
__credits__ = ("Sébastien Fievet <zyegfryed@gmail.com>,"
"Brandon Rhodes <brandon@rhodesmill.org>")
import codecs
def smart_encode_str(s):
"""Create a UTF-16 encoded PDF string literal for `s`."""
utf16 = s.encode('utf_16_be')
safe = utf16.replace('\x00)', '\x00\\)').replace('\x00(', '\x00\\(')
return ('%s%s' % (codecs.BOM_UTF16_BE, safe))
def handle_hidden(key, fields_hidden):
if key in fields_hidden:
return "/SetF 2"
else:
return "/ClrF 2"
def handle_readonly(key, fields_readonly):
if key in fields_readonly:
return "/SetFf 1"
else:
return "/ClrFf 1"
def handle_data_strings(fdf_data_strings, fields_hidden, fields_readonly):
for (key, value) in fdf_data_strings:
if type(value) is bool:
if value:
yield "<<\n/V/Yes\n/T (%s)\n%s\n%s\n>>\n" % (
smart_encode_str(key),
handle_hidden(key, fields_hidden),
handle_readonly(key, fields_readonly),
)
else:
yield "<<\n/V/Off\n/T (%s)\n%s\n%s\n>>\n" % (
smart_encode_str(key),
handle_hidden(key, fields_hidden),
handle_readonly(key, fields_readonly),
)
else:
yield "<<\n/V (%s)\n/T (%s)\n%s\n%s\n>>\n" % (
smart_encode_str(value),
smart_encode_str(key),
handle_hidden(key, fields_hidden),
handle_readonly(key, fields_readonly),
)
def handle_data_names(fdf_data_names, fields_hidden, fields_readonly):
for (key, value) in fdf_data_names:
yield "<<\n/V /%s\n/T (%s)\n%s\n%s\n>>\n" % (
smart_encode_str(value),
smart_encode_str(key),
handle_hidden(key, fields_hidden),
handle_readonly(key, fields_readonly),
)
def forge_fdf(pdf_form_url="", fdf_data_strings=[], fdf_data_names=[], fields_hidden=[], fields_readonly=[]):
"""Generates fdf string from fields specified
pdf_form_url is just the url for the form fdf_data_strings and
fdf_data_names are arrays of (key,value) tuples for the form fields. FDF
just requires that string type fields be treated seperately from boolean
checkboxes, radio buttons etc. so strings go into fdf_data_strings, and
all the other fields go in fdf_data_names. fields_hidden is a list of
field names that should be hidden fields_readonly is a list of field names
that should be readonly
The result is a string suitable for writing to a .fdf file.
"""
fdf = ['%FDF-1.2\n%\xe2\xe3\xcf\xd3\r\n']
fdf.append("1 0 obj\n<<\n/FDF\n")
fdf.append("<<\n/Fields [\n")
fdf.append(''.join(handle_data_strings(fdf_data_strings, fields_hidden, fields_readonly)))
fdf.append(''.join(handle_data_names(fdf_data_names, fields_hidden, fields_readonly)))
fdf.append("]\n")
if pdf_form_url:
fdf.append("/F (" + smart_encode_str(pdf_form_url) + ")\n")
fdf.append(">>\n")
fdf.append(">>\nendobj\n")
fdf.append("trailer\n\n<<\n/Root 1 0 R\n>>\n")
fdf.append('%%EOF\n\x0a')
return ''.join(fdf)