[英]How do I generate and download a PDF from markdown using Meteor
我有一个Meteor文档集合,其内容是使用markdown设置样式的(有关如何执行此操作的示例,请参见: 如何将Markdown与Meteor一起实际使用 )
我的程序包堆栈如下:
npm
大气层
查看文档时,我想向我的用户展示“以Download as PDF
按钮。 单击此选项会将文档的降价转换为PDF文件,然后通过浏览器下载。
转换过程受到限制; 它应在服务器上运行,但不允许将任何临时文件保存到服务器。
我该如何实现?
使用iron-router
,创建服务器端路由以提供PDF。
Router.route '/api/pdf/:_id',
name : 'generatePDF'
where: 'server'
action: ->
document= Documents.findOne @params._id
sanitize = Meteor.npmRequire 'sanitize-filename'
filename = sanitize(document.title).replace(/\s+/g, '-')
@response.writeHead 200,
'Content-Type': 'application/pdf'
'Content-Disposition': "attachment; filename=#{filename}.pdf"
markdown = document.content
Async.runSync (done)->
Meteor.npmRequire('markdown-pdf')
.from.string(markdown)
.to.buffer (err, buffer)->
done null, new BufferStream buffer
.result.pipe @response
上面的路由接收_id
作为路由参数。 这是用来检索相关的document
从Documents
集合。 然后,通过对document.title
进行消毒来生成PDF filename
。用连字符替换所有空格。
现在设置了响应头,以强制浏览器将PDF下载为带有已清理filename
。
PDF是使用markdown-pdf
包从document.content
markdown生成的。 此过程由于两个问题而变得复杂:
生成PDF的调用本质上是异步的,因此需要回调。 需要将其包装到Meteor的Async.runSynch
方法中,以将其转换为同步调用。 这将返回一个具有我们可以使用的result
属性的对象。
markdown-pdf
软件包具有to.buffer
方法,该方法返回包含生成的PDF的buffer
。 这使我们可以将所有内容保留在代码中,并且无需将临时文件保存到服务器。 要将这个buffer
传递到response
我们需要将其转换为流。 我使用辅助BufferStream
对象为我完成此操作(请参见下文)
使用此路由后,我只需要在显示模板上的某个位置放置“下载为PDF”按钮(下面的代码是Bootstrap 3类将Jade链接样式化为按钮)
a.btn.btn-primary(href='{{pathFor "generatePDF"}}' target='_blank') Download as PDF
最后,这是BufferStream
帮助器类:
stream = Meteor.npmRequire "stream"
class @BufferStream extends stream.Readable
constructor: (@source, @offset = 0) ->
throw new Meteor.Error 'InvalidBuffer', 'BufferStream source must be a buffer.' unless Buffer.isBuffer(@source)
super
@length = @source.length
_read: (size) ->
if @offset < @length
@push @source.slice @offset, @offset + size
@offset += size
@push null if @offset >= @length
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.