标签归档:php

HTML转为PDF的两种方案(含nodejs、PHP以及Python三种实现代码)

采用chrome headless方案

为什么要采用Chrome headless

因为wkhtmltopdf内置的为qt的webkit,已经很久不更新了,很多css3以及html5都支持不友好。

Chrome官方提供的页面转换为PDF的接口

https://chromedevtools.github.io/devtools-protocol/tot/Page#method-printToPDF

命令行方式

chrome --headless --print-to-pdf=path/to/file.pdf https://example.com

参考:HTML to PDF conversion using Chrome pdfium?

NodeJS扩展

html-pdf-chrome HTML to PDF converter via Chrome/Chromium.

PHP扩展

chrome-html-to-pdf Converts HTML to PDF using Google Chrome

Chrome命令行参数列表

List of Chromium Command Line Switches

采用Qt的Webkit(PyQt5)

由于当前的chrome转换存在BUG,转换大文件时内存消耗特别大,生成的文件也比较大,测试了10多种方法后,最后决定采用PyQt5来做

#!/usr/bin/env python3

import sys
import argparse

from PyQt5.QtCore import QUrl, QMarginsF
from PyQt5.QtGui import QPageLayout, QPageSize
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWidgets import QApplication


class PrinterView(QWebEngineView):
    def __init__(self, url, filename, do_preview, parent=None):
        super(PrinterView, self).__init__(parent)
        self.do_preview = do_preview
        self.setUrl(QUrl(url))
        self.setZoomFactor(1)
        self.loadFinished.connect(self.load_finished)
        self.filename = filename

    def load_finished(self):
        if self.do_preview:
            self.show()
        else:
            pageLayout = QPageLayout(QPageSize(QPageSize.A5), QPageLayout.Portrait,
                                     QMarginsF(0, 0, 0, 0))
            self.page().printToPdf(self.filename, pageLayout)
            self.page().pdfPrintingFinished.connect(on_pdf_finished)


def on_pdf_finished(result):
    if result:
        print(result)
        QApplication.exit()
    else:
        QApplication.exit(1)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    parser = argparse.ArgumentParser()
    parser.add_argument("--url", "-i", help="Input URL (http://example.com, file:///home/user/example.html, ...)",
                        required=True)
    parser.add_argument("--output", "-o", help="Write pdf to this file", required=True)
    parser.add_argument("--preview", "-p", help="Open preview", action="store_true")
    args = parser.parse_args()
    a = PrinterView(args.url, args.output, args.preview)
    sys.exit(app.exec_())

 采用qt打印

import sys
import argparse

from PyQt5.QtCore import QUrl, QMarginsF
from PyQt5.QtGui import QPageLayout, QPageSize
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage, QWebEngineProfile
from PyQt5.QtWidgets import QApplication
from PyQt5.QtPrintSupport import QPrinter, QPrintDialog


class PrinterView(QWebEngineView):
    def __init__(self, url, filename, do_preview, parent=None):
        self.printer = QPrinter()
        self.printer.setPageSize(QPrinter.A5)
        self.printer.setOrientation(QPrinter.Portrait)
        self.printer.setOutputFormat(QPrinter.PdfFormat)
        self.printer.setOutputFileName(filename)
        self.printer.setPageMargins(0, 0, 0, 0, QPrinter.Millimeter)
        super(PrinterView, self).__init__(parent)
        self.do_preview = do_preview
        self.page().profile().setHttpCacheMaximumSize(5 * 1024 * 1024 * 1024)
        self.page().profile().setHttpCacheType(QWebEngineProfile.MemoryHttpCache)
        self.setUrl(QUrl(url))
        self.setZoomFactor(1)
        self.loadFinished.connect(self.load_finished2)
        self.filename = filename

    def load_finished(self):
        if self.do_preview:
            self.show()
        else:
            pageLayout = QPageLayout(QPageSize(QPageSize.A5), QPageLayout.Portrait,
                                     QMarginsF(0, 0, 0, 0))
            self.page().printToPdf(self.filename, pageLayout)
            self.page().pdfPrintingFinished.connect(on_pdf_finished)

    def load_finished2(self):
        self.show()
        self.page().print(self.printer, on_pdf_finished)


def on_pdf_finished(result):
    if result:
        print(result)
        QApplication.exit()
    else:
        QApplication.exit(1)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    parser = argparse.ArgumentParser()
    parser.add_argument("--url", "-i", help="Input URL (http://example.com, file:///home/user/example.html, ...)",
                        required=True)
    parser.add_argument("--output", "-o", help="Write pdf to this file", required=True)
    parser.add_argument("--preview", "-p", help="Open preview", action="store_true")
    args = parser.parse_args()
    a = PrinterView(args.url, args.output, args.preview)
    sys.exit(app.exec_())

使用firefox的pdf

slimer-html-pdf – convert any HTML document to PDF format using slimerjs (Gecko)

大文件合并(Python)

 def on_pdf_finished(self, result):
        if result:
            print(result + ', total ' + str(self.total))
        else:
            print("导出失败")
        self.printed = self.printed + 1
        print('导出第', self.printed, '本')
        if self.printed < self.total:
            self.print_book()
        else:
            print('开始合并')
            merger = PdfFileMerger()
            for index in range(0, self.total):
                filepath = self.filename + '.' + str(index) + '.pdf'
                merger.append(filepath)
                print('合并第', index, '本')
            merger.write(self.filename)
            merger.close()
            print('合并完成,开始清除临时文件')
            # for index in range(0, self.total):
            #     filepath = self.filename + '.' + str(index) + '.pdf'
            #     os.remove(filepath)
            print('清除临时文件完成')
            QApplication.exit()

使用Vagrant+CentOS 7搭建PHP7开发环境(含centos7.box直接下载地址)

Vagrant是一款基于命令行的虚拟机管理软件,可以用来快速部署统一的开发环境。

下载Vagrant

https://www.vagrantup.com/downloads.html

下载CentOS 7 Box

官方box下载地址

https://app.vagrantup.com/boxes/search

第三方box下载地址

http://www.vagrantbox.es/

使用原生下载

https://app.vagrantup.com/centos/boxes/7

vagrant init centos/7
vagrant up

vagrant 配置

  config.vm.network "public_network", ip: "192.168.31.245"
  config.vm.synced_folder "d:/data", "/data"
  config.vm.synced_folder "d:/phpcode", "/phpcode"

通过下载工具下载centos 7 box

官方box文件下载地址:http://cloud.centos.org/centos/7/vagrant/x86_64/images/

百度网盘box文件下载地址

  • CentOS 7: https://pan.baidu.com/s/1kVlAz59

添加并运行box

vagrant box add centos7 CentOS-7.box
vagrant init centos7
vagrant up

基础系统安装

基本系统安装

vagrant ssh
sudo passwd vagrant
sudo yum groupinstall "Development tools" -y
sudo yum install vim gcc kernel-devel kenel-devel-`uname -r`

禁止selinux

sudo setenforce 0 

sudo vi /etc/selinux/config

SELINUX=disabled

停止防火墙

sudo systemctl disable firewalld
sudo systemctl stop firewalld

更新系统

sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
sudo yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
sudo yum install yum-utils
sudo yum-config-manager --enable remi-php72
sudo yum update
sudo yum install php-gd php-pdo php-opcache php-fpm php-pecl-redis php-pecl-mysql php-pecl-mysql php-mbstring php-intl php-cli php-xml
sudo yum install nginx -y
sudo yum install mariadb mariadb-server -y

修改nginx配置

mkdir /data/log/nginx /data/run/nginx -p
sudo service nginx stop 
sudo vim /etc/nginx/nginx.conf

nginx.conf配置修改如下:

user vagrant;
error_log /data/log/nginx/error.log;
pid /data/run/nginx/nginx.pid;

access_log  /data/log/nginx/access.log  main;

include /data/phpcode/projectname/vagrant/nginx/app.conf;

测试nginx配置

sudo nginx -t

修改nginx service配置:

sudo vim /usr/lib/systemd/system/nginx.service

nginx.service修改内容如下:

[Service]
PIDFile=/data/run/nginx/nginx.pid

重新加载service

sudo systemctl daemon-reload
sudo systemctl start nginx

修改PHP配置

mkdir  /data/run/php-fpm/session /data/run/php-fpm/wsdlcache /data/run/php-fpm/opcache /data/log/php-fpm/ -p
sudo service php-fpm stop
sudo vim /etc/php-fpm.d/www.conf

配置内容

user = vagrant
group = vagrant
php_value[session.save_path]    = /data/run/php-fpm/session
php_value[soap.wsdl_cache_dir]  = /data/run/php-fpm/wsdlcache
php_value[opcache.file_cache]  = /data/run/php-fpm/opcache
php_admin_value[error_log] = /data/log/php-fpm/www-error.log
slowlog = /data/log/php-fpm/www-slow.log
request_slowlog_timeout = 1

重启

sudo service php-fpm stop

配置Mysql

mkdir /data/mysql /data/run/mariadb /data/log/mariadb -p
sudo service mariadb stop
sudo vim /etc/my.cnf

mysqld配置

[mysqld]
datadir=/data/mysql
socket=/usr/lib/mysql/mysql.sock

[mysqld_safe]
log-error=/data/log/mariadb/mariadb.log
pid-file=/data/run/mariadb/mariadb.pid

mysql client 配置

[client]

初始化数据库

sudo /usr/libexec/mariadb-prepare-db-dir mariadb.service

修改systemd配置

sudo vim /usr/lib/systemd/system/mariadb.service

配置内容

User=vagrant
Group=vagrant

重载systemd

sudo systemctl daemon-reload
sudo systemctl start mariadb

修改mysql账号密码

'/usr/bin/mysqladmin' -u root password 'new-password'
'/usr/bin/mysqladmin' -u root -h localhost.localdomain password 'new-password'

# Alternatively you can run:
'/usr/bin/mysql_secure_installation'

配置composer

下载安装文件

php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');"

安装

php composer-setup.php

删除安装文件

php -r "unlink('composer-setup.php');"

设置全局路径(windows请按参考文档设置)

sudo mv composer.phar /usr/bin/composer

配置使用国内镜像

composer config -g repo.packagist composer https://packagist.phpcomposer.com

fedora 26快速安装PHP开发环境

Nvidia显卡驱动

sudo dnf config-manager --add-repo=http://negativo17.org/repos/fedora-nvidia.repo  
sudo dnf install kernel-devel dkms-nvidia -y

Vim & git & hg & svn

sudo dnf install vim git hg subversion -y

sudo不需要密码

sudo visudo

%wheel  ALL=(ALL)       NOPASSWD: ALL

禁止selinux

sudo setenforce 0 

sudo vi /etc/selinux/config

SELINUX=disabled

右键打开控制台窗口

sudo dnf install nautilus-open-terminal -y

Development tools

sudo dnf groupinstall "Development tools" -y

nginx & php & mysql

sudo dnf install  nginx php-cli php-devel php-mbstring php-opcache php-mysqlnd php-intl php-mcrypt php-pdo php-xml php-pecl-memcache  php-pecl-redis php-pecl-sphinx php-pecl-zip php-pgsql php-xdebug php-gd  php-pecl-redis  php-pecl-imagick  php-fpm -y
sudo dnf install mariadb mariadb-server -y
sudo systemctl enable php-fpm nginx mariadb

修改nginx配置

sudo service nginx stop 
sudo vim /etc/nginx/nginx.conf

nginx.conf配置修改如下:

user ning;
error_log /data/log/nginx/error.log;
pid /data/run/nginx.pid;

access_log  /data/log/nginx/access.log  main;

include /data/phpcode/projectname/vagrant/nginx/app.conf;

测试nginx配置

sudo nginx -t

修改nginx service配置:

sudo vim /usr/lib/systemd/system/nginx.service

nginx.service修改内容如下:

[Service]
PIDFile=/data/run/nginx.pid
ExecStartPre=/usr/bin/rm -f /data/run/nginx.pid

重新加载service

sudo systemctl daemon-reload
sudo systemctl start nginx

修改PHP配置

sudo service php-fpm stop
sudo vim /etc/php-fpm.d/www.conf

配置内容

user = ning
group = ning
listen = 127.0.0.1:9000
listen.acl_users = ning
php_value[session.save_path]    = /log/php/session
php_value[soap.wsdl_cache_dir]  = /log/php/wsdlcache
;php_value[opcache.file_cache]  = /log/php/opcache

重启

sudo service php-fpm stop

配置composer

下载安装文件

php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');"

安装

php composer-setup.php

删除安装文件

php -r "unlink('composer-setup.php');"

设置全局路径(windows请按参考文档设置)

sudo mv composer.phar ~/bin/composer

配置使用国内镜像

composer config -g repo.packagist composer https://packagist.phpcomposer.com

使用国内镜像快速安装composer以及yii2(附安装脚本)

通过中国镜像安装composer

参考文章 如何安装 Composer

下载安装文件

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === '93b54496392c062774670ac18b134c3b3a95e5a5e5c8f1a9f115f203b75bf9a129d5daa8ba6a13e2cc8a1da0806388a8') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

安装

php composer-setup.php

删除安装文件

php -r "unlink('composer-setup.php');"

设置全局路径(windows请按参考文档设置)

sudo mv composer.phar /usr/local/bin/composer

配置使用国内镜像

composer config -g repo.packagist composer https://packagist.phpcomposer.com

安装Yii2

参考文章 Install via Composer

首先安装 Composer Asset Plugin

composer global require "fxp/composer-asset-plugin:^1.2.0"

安装基础模板

php composer.phar create-project yiisoft/yii2-app-basic yiitest

安装高级模板

php composer.phar create-project yiisoft/yii2-app-advanced yiitest

安装过程中如果提示“please create a GitHub OAuth token to go over the API rate limit”,登录github,在https://github.com/settings/tokens生成一个token,权限只需要勾选repo即可

进入项目目录

cd yiitest

测试安装环境

php requirements.php

初始化项目

 ./init

运行项目

./yii serve/index -h
./yii serve/index -t="@frontend/web"
./yii serve/index -t="@backend/web"