我是ReportLab的新手,我正在创建一个简单的文档,员工将文本输入到网站上的文本区域,将其保存到数据库中,然后从数据库中提取以通过ReportLab创建PDF。我看到的问题是,如果用户输入的文本包含2个段落之间的换行符,则在创建PDF时不会遵循该换行符。
当我通过相同的Python脚本将文本内容直接打印到屏幕上时,一切都是正确的:
与流行的看法相反,Lorem Ipsum不仅仅是随机文本。它 源于公元前45年的一段古典拉丁文学作品 它已有2000多年的历史。理查德麦克林托克,拉丁教授 在弗吉尼亚州的汉普登 - 悉尼学院,查找了一个比较模糊的人 拉丁语单词,consectetur,来自Lorem Ipsum段落,然后去 通过古典文学中的词汇,发现了 无可置疑的来源。 Lorem Ipsum来自1.10.32和 由西塞罗撰写的“de Finibus Bonorum et Malorum”(极端的善与恶)的1.10.33,写于公元前45年。这本书是一篇论文 道德理论,在文艺复兴时期非常流行。第一行 Lorem Ipsum,“Lorem ipsum dolor sit amet ..”,来自一条线路 第1.10.32节。
与流行的看法相反,Lorem Ipsum不仅仅是随机文本。它 源于公元前45年的一段古典拉丁文学作品 它已有2000多年的历史。理查德麦克林托克,拉丁教授 在弗吉尼亚州的汉普登 - 悉尼学院,查找了一个比较模糊的人 拉丁语单词,consectetur,来自Lorem Ipsum段落,然后去 通过古典文学中的词汇,发现了 无可置疑的来源。 Lorem Ipsum来自1.10.32和 由西塞罗撰写的“de Finibus Bonorum et Malorum”(极端的善与恶)的1.10.33,写于公元前45年。这本书是一篇论文 道德理论,在文艺复兴时期非常流行。第一行 Lorem Ipsum,“Lorem ipsum dolor sit amet ..”,来自一条线路 第1.10.32节。
然而,在PDF中它看起来像:
与流行的看法相反,Lorem Ipsum不仅仅是随机文本。它 源于公元前45年的一段古典拉丁文学作品 它已有2000多年的历史。理查德麦克林托克,拉丁教授 在弗吉尼亚州的汉普登 - 悉尼学院,查找了一个比较模糊的人 拉丁语单词,consectetur,来自Lorem Ipsum段落,然后去 通过古典文学中的词汇,发现了 无可置疑的来源。 Lorem Ipsum来自1.10.32和 由西塞罗撰写的“de Finibus Bonorum et Malorum”(极端的善与恶)的1.10.33,写于公元前45年。这本书是一篇论文 道德理论,在文艺复兴时期非常流行。第一行 Lorem Ipsum,“Lorem ipsum dolor sit amet ..”,来自一条线路 第1.10.32节。对于流行的看法,Lorem Ipsum并不简单 随机文字。它源于一段古典拉丁文学 从公元前45年开始,它已有2000多年的历史。 Richard McClintock,拉丁文 弗吉尼亚州汉普顿 - 悉尼学院的教授抬头看了一眼 来自Lorem Ipsum段落的更加模糊的拉丁语单词,consectetur,和 经历古典文学中的词汇, 发现了无可置疑的来源。 Lorem Ipsum来自各个部分 西塞罗的“de Finibus Bonorum et Malorum”(极端的善与恶)的1.10.32和1.10.33,写于公元前45年。这本书是一篇论文 伦理学理论,在文艺复兴时期非常流行。该 Lorem Ipsum的第一行,“Lorem ipsum dolor sit amet ..”,来自 第1.10.32节中的一行。
起初我认为这是数据库中的文本格式问题,但在我能够在PDF创建之前正确打印出内容后,我知道这不是问题。
我是否错过了段落的简单样式输入?我有点失落,因为我还不知道ReportLab的所有细节。
以下是脚本中的ReportLab代码段。 employeeQuestion1
是在创建PDF之前以正确的格式打印出来的。
def stylesheet():
styles= {
'default': ParagraphStyle(
'default',
fontName='SourceSansPro-Bold',
fontSize=10,
leading=12,
leftIndent=0,
rightIndent=0,
firstLineIndent=0,
alignment=TA_LEFT,
spaceBefore=0,
spaceAfter=0,
bulletFontName='Times-Roman',
bulletFontSize=10,
bulletIndent=0,
textColor= black,
backColor=None,
wordWrap=None,
borderWidth= 0,
borderPadding= 0,
borderColor= None,
borderRadius= None,
allowWidows= 1,
allowOrphans= 0,
textTransform=None,
endDots=None,
splitLongWords=1,
),
}
styles['employee_response'] = ParagraphStyle(
'employee_response',
parent=styles['default'],
fontName='SourceSansPro-Regular',
fontSize=10,
spaceAfter=10,
leftIndent=20
)
return styles
def build_flowables(stylesheet):
return [
Paragraph('{0}'.format(employeeQuestion1), stylesheet['employee_response']),
]
def build_pdf(filename, flowables):
doc = SimpleDocTemplate(filename,
rightMargin=inch/2,
leftMargin=inch/2,
topMargin=inch/2,
bottomMargin=inch/2,
pagesize=letter,
)
doc.addPageTemplates(
[
PageTemplate(
frames=[
Frame(
doc.leftMargin,
doc.bottomMargin,
doc.width,
doc.height,
id=None
),
]
),
]
)
doc.build(flowables)
build_pdf('/etc/review_app/reviews/{0}.pdf'.format(pdfFileName), build_flowables(stylesheet()))
感谢您的帮助!
答案 0 :(得分:0)
我通过将新行转换为public void Receive(string hostName, string queueName, string type, IEnumerable<string> routingKeys, string exchange)
{
//Initializes the MediatorHandler`s factory
InitializeFactory();
var mediatorHandler = _mediatorHandlers[type];
//RabbitMQ configuration
var userName = _configuration["Messaging:UserName"];
var password = _configuration["Messaging:Password"];
var numberOfConsumers = int.Parse(_configuration["Messaging:NumerOfConsumers"]);
var channels = int.Parse(_configuration["Messaging:Channels"]);
var factory = new ConnectionFactory() { HostName = hostName, UserName = userName, Password = password };
var connection = factory.CreateConnection();
for (int i = 1; i <= channels; i++)
{
var channel = connection.CreateModel();
var prefetchQuantity = _configuration["Messaging:PrefetchQuantity"];
channel.BasicQos(0, Convert.ToUInt16(prefetchQuantity), false);
//Declaring the exchange
channel.ExchangeDeclare(exchange, ExchangeType.Direct);
//Declaring the queue and creating its routing key bindings
channel.QueueDeclare(queueName, true, false, false, null);
foreach (var routingKey in routingKeys)
{
channel.QueueBind(queueName, exchange, routingKey);
}
for (int j = 1; j <= numberOfConsumers; j++)
{
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, e) =>
{
try
{
mediatorHandler.Handle(model, e, _mediator);
channel.BasicAck(e.DeliveryTag, false);
}
catch (Exception exception)
{
Console.WriteLine(exception);
channel.BasicNack(e.DeliveryTag, false, true);
}
};
channel.BasicConsume(queue: queueName,
autoAck: false,
consumer: consumer);
}
}
}
标记解决了这个问题:
<br />
希望这可以帮助有同样问题的人