React Nodejs - jsx 中的自定义@font-face 用于生成 PDF

React Nodejs - Custom @font-face in jsx for PDF generation

我有一个 React 项目,其中部分功能涉及向运行 PhantomJS 和 html-pdf 插件的 Nodejs 服务器发送请求,以创建一个 pdf,该 pdf 通过我的 React 组件构建节点服务器。我遇到的问题实际上是将自定义字体嵌入到我的反应组件中。我有一个 base64 编码的字体集,与一堆文件相比,它更容易包含,但由于 React 在 CSS 中的加载方式,我不断收到错误。

这是在我的 NodeJS 服务器上调用以生成 PDF 的函数:

exports.order = (req, res, next) => {

  phantom.create().then(function(ph) {
    ph.createPage().then(function(page) {
      // page.viewportSize = { width: 600, height: 600 };
      page.open(`http://localhost:3005/print/work/${req.params.id}`).then(function(status) {
        page.property('content').then(function(content) {
          pdf.create(content, options).toBuffer(function(err, buffer){

              res.writeHead(200, {
               'Content-Type': 'application/pdf',
               'Content-Disposition': `attachment; filename=order-${req.params.id}.pdf`,
               'Content-Length': buffer.length
             });
             res.end(buffer);
          });
          page.close();
          ph.exit();
        });
      });
    });
  });

}

这是包含 PDF HTML 的实际 React 组件:

var React = require('react');
var moment = require('moment');

class PrintWorkOrder extends React.Component {
  render() {
    var order = this.props;

    var s = {
      body: {
        width: '100%',
        float: 'none',
        fontFamily: 'Helvetica',
        color: '#000',
        display: 'block',
        fontSize: 10,
      }
    }
    return (
      <div style={s.body}>
         I shortened the content in her for brevity
      </div>
    )
  }
}

module.exports = PrintWorkOrder;

该功能目前有效,只是现在我需要添加一些不是 Helvetica 的自定义字体,我在使用当前实现解决这个问题时遇到了问题。有人对此有任何见解吗?

我也有同样的问题,我做的是将front编码成base64,然后把它写成

font.css

@font-face {
  font-family: 'fontName';
  src: url(data:application/x-font-woff;charset=utf-8;base64,<base64>) format('woff'),
  font-weight: normal;
  font-style: normal;
}

诀窍是读取 CSS 文件内容并将其作为样式标签注入 DOM 标记

React.createElement('style', { dangerouslySetInnerHTML: { __html: this.props.children } });

所以要这样做: 对于第二行代码,它创建样式元素的作用。你可以做的是编写一个组件,从 .css 文件中读取内容,然后将内容放入样式元素中,如下所示:

Style.js

var React = require('react');
export default class Style extends React.Component {
    static propTypes = {
        children: React.PropTypes.string.isRequired
    };

    render() {
        return React.createElement('style', { dangerouslySetInnerHTML: { __html: this.props.children } });
    }
}

修改PrintWorkOrder.js

var React = require('react');
var moment = require('moment');
var fs = require('fs');
var path = require('path');
var Style = require('./Style');

const readFile = (filePath) => fs.readFileSync(path.resolve(__dirname, filePath)).toString();

class PrintWorkOrder extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            styles: []
        }
    }

    componentWillMount() {
        this.setState({
            styles: [
                readFile('font.css') // Assuming putting font.css same location with PrintWorkOrder component
            ]
        })
    }

    render() {
        var order = this.props;

        var s = {
            body: {
                width: '100%',
                float: 'none',
                fontFamily: 'Helvetica',
                color: '#000',
                display: 'block',
                fontSize: 10,
            }
        }

        return (
            <html>
                <head>
                    {/* Here to render all the styles */}
                    {this.state.styles.map(s => (<Style>{s}</Style>))}
                </head>
                <body>
                    <div style={s.body}>
                        I shortened the content in her for brevity
                    </div>
                </body>
            </html>
        );
    }
}

module.exports = PrintWorkOrder;