繁体   English   中英

如何使用Meteor从Markdown生成和下载PDF

[英]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作为路由参数。 这是用来检索相关的documentDocuments集合。 然后,通过对document.title进行消毒来生成PDF filename 。用连字符替换所有空格。

现在设置了响应头,以强制浏览器将PDF下载为带有已清理filename

PDF是使用markdown-pdf包从document.content markdown生成的。 此过程由于两个问题而变得复杂:

  1. 生成PDF的调用本质上是异步的,因此需要回调。 需要将其包装到Meteor的Async.runSynch方法中,以将其转换为同步调用。 这将返回一个具有我们可以使用的result属性的对象。

  2. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM