基于WPSOffice+Pywpsrpc构建Docker镜像,实现文档转换和在线预览服务
背景
产品功能需要实现标准文档的在线预览功能,由于DOC文档没办法直接通过浏览器打开预览,需要提前转换为PDF文档或者HTML页面。
经过测试发现DOC转为HTML页面后文件提交较大,而且生成的静态资源文件较多,需要额外搭建Web容器存放,所以还是考虑转换为PDF格式文档。
选型
需求明确后就要考虑如何实现了,这里对比了开源文档转换工具例如:kkFileView、documents4j、poi、openoffice、aspose、Spire.Office等。
选型主要考虑以下几个方面:
1、转换为PDF文档后是否会失真,也就是和原DOC文档的格式还原度;
2、是否支持大文档,有些标准文档超过40M用MSOffice打开很卡;
3、工具收费情况。
简单说下结论:
1、上面几个工具全部验证了一遍,后发现都不太合适,原因有二,免费工具会失真或者限制了文档的大小,收费的工具可以用但是贵;
2、最后选择用WPS进行文档格式转换,原因很简单,首先WPS有个人版是可以免费使用的,其实WPS转换PDF文档的还原度相当高,另外客户方已经采购了WPS的企业版本,如果后续文档转换失真也有个说法;
3、解决方案:基于CentOS安装WPS,通过Python的Pywpsrpc组件调用WPS的文档转换功能,对外提供文档转换服务。
镜像构建
服务镜像已构建完成,如有需要可以联系笔者V:hsky23557544
基础镜像
由于涉及安装的组件太多,编写Dockerfile的话太麻烦也不便于试错,所以决定先拉取一个基础的CentOS镜像,把软件服务都安装好,最后通过docker commit将容器打成镜像。
1、基础镜像docker pull centos:7.6.1810
2、启动容器docker run --name centos --network host -dit --privileged=true centos:7.6.1810 /usr/sbin/init
3、更新到国内的YUM源,加速后面的软件安装,网上教程很多不增加篇幅
安装CentOS桌面
pywpsrpc需要依赖系统桌面调用WPS的API,如需headless运行可以参考:https://github.com/timxx/pywpsrpc/wiki/Run-on-Server
yum -y install epel-release
yum groupinstall "GNOME Desktop"
systemctl isolate graphical.target
systemctl set-default graphical.target
yum install xrdp -y
yum install tigervnc-server -y
# 设置vnc访问密码
vncpasswd root
systemctl start xrdp
systemctl enable xrdp
WPSOffice安装
1、官网Linux版本安装包下载:https://linux.wps.cn/
2、安装yum localinstall wps-office-11.1.0.11711-1.x86_64.rpm
安装WPSOffice依赖的字体
推荐使用开源项目安装:https://github.com/dv-anomaly/ttf-wps-fonts
git clone https://github.com/iamdh4/ttf-wps-fonts.git
cd ttf-wps-fonts
sudo sh install.sh
rm -rf /tmp/ttf-wps-fonts
安装Python3.6
开始用Python3.9版本安装pywpsrpc的时候直接报错了,查阅了一些pywpsrpc的issues发现需要使用Python3.6.x版本,另外pywpsrpc没有arm版本需要自行编译whl安装。
1、下载安装包:https://registry.npmmirror.com/-/binary/python/3.6.15/Python-3.6.15.tgz
2、安装依赖:yum install -y gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl--devel
3、编译安装
# 解压压缩包
tar -zxvf Python-3.6.15.tgz
# 进入文件夹
cd Python-3.6.15
# 配置安装位置
./configure prefix=/usr/local/python3
# 安装
make && make install
# 建立软连接
ln -s /usr/local/python3/bin/python3.6 /usr/bin/python3
ln -s /usr/local/python3/bin/pip3.6 /usr/bin/pip3
4、安装pywpsrpc:pip3 install pywpsrpc -i https://pypi.tuna.tsinghua.edu.cn/simple
5、安装flask:pip3 install flask -i https://pypi.tuna.tsinghua.edu.cn/simple
如果提示使用pip安装依赖包时提示SSL证书验证的问题,需要重新编译安装openssl,操作如下:
# 下载源码包
wget http://www.openssl.org/source/openssl-1.1.1l.tar.gz
# 编译安装
mkdir /usr/local/ssl
./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl no-zlib
make && make install
echo "/usr/local/ssl/lib" >> /etc/ld.so.conf
测试是否安装好,ldconfig -v 显示出相关内容,并查看/usr/local/ssl目录下确实有安装好的文件
# 回到Python源吗目录下
make clean
# 配置安装位置
./configure prefix=/usr/local/python3
修改Modules/Setup文件

make && make install
ln -s /usr/local/python3/bin/python3 /usr/local/bin/python3
ln -s /usr/local/python3/bin/pip3 /usr/local/bin/pip3
安装QT5
1、下载安装包:https://download.qt.io/archive/qt/5.12/5.12.12/
2、安装依赖包:yum -y install mesa-libGL-devel mesa-libGLU-devel freeglut-devel gdb
3、安装包授权:chmod +x qt-opensource-linux-x64-5.12.12.run
4、使用mstsc远程登录CentOS桌面,执行./qt-opensource-linux-x64-5.12.12.run通过图形化界面安装,安装时会提示注册按提示信息操作即可
文档转换服务
import traceback, uuid, os
from flask import Flask, request, send_from_directory
from pywpsrpc.rpcwpsapi import (createWpsRpcInstance, wpsapi)
from pywpsrpc.common import (S_OK, QtApp)
app = Flask(__name__)
# 设置文件上传保存路径
app.config['UPLOAD_FOLDER'] = '/tmp'
# MAX_CONTENT_LENGTH设置上传文件的大小,单位字节
app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024 * 1024
formats = {
"doc": wpsapi.wdFormatDocument,
"docx": wpsapi.wdFormatXMLDocument,
"rtf": wpsapi.wdFormatRTF,
"html": wpsapi.wdFormatHTML,
"pdf": wpsapi.wdFormatPDF,
"xml": wpsapi.wdFormatXML,
}
class ConvertException(Exception):
def __init__(self, text, hr):
self.text = text
self.hr = hr
def __str__(self):
return """Convert failed:
Details: {}
ErrCode: {}
""".format(self.text, hex(self.hr & 0xFFFFFFFF))
def convert_to(path, format, abort_on_fails=False):
hr, rpc = createWpsRpcInstance()
if hr != S_OK:
raise ConvertException("Can't create the rpc instance", hr)
hr, app = rpc.getWpsApplication()
if hr != S_OK:
raise ConvertException("Can't get the application", hr)
try:
# we don't need the gui
app.Visible = False
docs = app.Documents
def _handle_result(hr):
if abort_on_fails and hr != S_OK:
raise ConvertException("convert_file failed", hr)
hr = convert_file(path, docs, format)
_handle_result(hr)
except Exception as e:
print(traceback.format_exc())
app.Quit(wpsapi.wdDoNotSaveChanges)
def convert_file(file, docs, format):
hr, doc = docs.Open(file, ReadOnly=True)
if hr != S_OK:
return hr
out_dir = os.path.dirname(os.path.realpath(file)) + "/out"
os.makedirs(out_dir, exist_ok=True)
# you have to handle if the new_file already exists
new_file = out_dir + "/" + os.path.splitext(os.path.basename(file))[0] + "." + format
ret = doc.SaveAs2(new_file, FileFormat=formats[format])
# always close the doc
doc.Close(wpsapi.wdDoNotSaveChanges)
return ret
@app.route("/convert", methods=["POST"])
def do_convert():
try:
# 转换格式参数
convert_format = request.form['format']
# 获取文件参数
file = request.files['file']
# 文件后缀
file_ext = file.filename.rsplit('.')[-1]
file_name_uuid = str(uuid.uuid4())
# UUID文件名
file_name = file_name_uuid + "." + file_ext
# 保存文件
file.save(os.path.join(app.config['UPLOAD_FOLDER'], file_name))
# 文件转换
print("开始转换文档[%s]" % file_name)
convert_to(os.path.join(app.config['UPLOAD_FOLDER'], file_name), convert_format, True)
print("文档转换完成[%s]" % file_name)
# 返回转换后的文件
convert_file_name = file_name_uuid + "." + convert_format
return send_from_directory(app.config['UPLOAD_FOLDER'] + '/out', convert_file_name, as_attachment=True)
except Exception as e:
print('文档转换时发生错误')
print(traceback.format_exc())
return {"success": False}
if __name__ == "__main__":
app.run(host="0.0.0.0", port=9000)
使用mstsc远程登录CentOS桌面,执行启动脚本:
#!/bin/bash
set -e
export PATH=$PATH:/opt/kingsoft/wps-office/office6
export LD_LIBRARY_PATH=/opt/Qt5.12.12/5.12.12/gcc_64/lib
python3 /root/converter.py
服务验证
1、远程桌面登录CentOS桌面后能够正常打开WPS软件,没有提示字体依赖错误;
2、文档转换接口测试:
curl --location --request POST 'http://10.32.x.x:9000/convert' \
--header 'User-Agent: Apifox/1.0.0 (https://apifox.com)' \
--header 'Accept: */*' \
--header 'Host: 10.32.x.x:9000' \
--header 'Content-Type: multipart/form-data; boundary=--------------------------851319197095122366611715' \
--form 'format="pdf"' \
--form 'file=@"需要转换的DOC文档路径"'
基于WPSOffice+Pywpsrpc构建Docker镜像,实现文档转换和在线预览服务的更多相关文章
- OFFICE 文档转换为html在线预览
OFFICE 文档在线预览方案很多: 服务器先转换为PDF,再转换为SWF,最后通过网页加载Flash预览,比如flexpaper Office文档直接转换为SWF,通过网页加载Flash预览 微软的 ...
- 将vue文档下载到本地预览
1下载:https://github.com/vuejs/cn.vuejs.org 到本地 2. npm install npm start # 开发服务器地址为 http://localhost ...
- word文档在线预览解决方案
花了一整天在网上翻关于 “word文档在线预览解决方案” 相关的资料,感觉实现难度比较大还是用PDF来解决好了.. 下面列一下比较好的参考资料吧 参考资料 前端实现在线预览pdf.word.xls.p ...
- 基于开源方案构建统一的文件在线预览与office协同编辑平台的架构与实现历程
大家好,又见面了. 在构建业务系统的时候,经常会涉及到对附件的支持,继而又会引申出对附件在线预览.在线编辑.多人协同编辑等种种能力的诉求. 对于人力不是特别充裕.或者项目投入预期规划不是特别大的公司或 ...
- 基于url-to-pdf-api构建docker镜像,制作一个网页另存服务
基于url-to-pdf-api构建docker镜像,制作一个网页另存服务 业务背景: 需要根据一个url路径打印这个网页的内容 解决方案: 1.使用wkhtml2pdf 2.使用puppeteer ...
- 使用Jenkins pipeline流水线构建docker镜像和发布
新建一个pipeline job 选择Pipeline任务,然后进入配置页面. 对于Pipeline, Definition选择 "Pipeline script from SCM" ...
- 构建Docker镜像两种方式的比较-Dockerfile方式和S2I方式
前言 写Dockerfile是构建Docker镜像最通常的方式,接触过Docker的童鞋多少了解一些.前段时间研究OpenShift(paas的一种),发现了另外一种构建Docker镜像的方式:S2I ...
- Maven插件构建Docker镜像
背景 微服务架构下,微服务在带来良好的设计和架构理念的同时,也带来了运维上的额外复杂性,尤其是在服务部署和服务监控上.单体应用是集中式的,就一个单体跑在一起,部署和管理的时候非常简单,而微服务是一个网 ...
- [转] 构建Docker镜像两种方式的比较-Dockerfile方式和S2I方式
原文地址:https://www.cnblogs.com/tianshifu/p/8127837.html 前言 写Dockerfile是构建Docker镜像最通常的方式,接触过Docker的童鞋多少 ...
- 使用Buildpacks高效构建Docker镜像
1. 前言 Spring Boot 2.3.0.RELEASE 正式发布了几天了,其中有个新的特性:可以将Spring Boot应用代码直接打包为Docker镜像.这是什么科技?我赶紧去官网查了一番才 ...
随机推荐
- cpu,gpu的种类
- ZS Shuffles Cards 题解
ZS Shuffles Cards 题解 我们把每一次抽一些数字牌再抽到 joker 视作一局游戏. 每局期望轮数 首先考虑 \(f_i\) 表示每一局游戏抽出 \(i\) 张牌的概率. 那么就是先抽 ...
- Codespaces个性化后台服务器配置指南
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 前文概览 在前文<浏览器上写代码,4核8G微软服 ...
- 文盘Rust -- 生命周期问题引发的 static hashmap 锁
2021年上半年,撸了个rust cli开发的框架,基本上把交互模式,子命令提示这些cli该有的常用功能做进去了.项目地址:https://github.com/jiashiwen/interactc ...
- MQTT vs. XMPP,哪一个才是IoT通讯协议的正解
MQTT vs. XMPP,哪一个才是IoT通讯协议的正解 这是个有趣的话题! 先来聊几个小故事. 关于我和MQTT 我在人生第一个IoT项目里,第一次接触到MQTT协议. 我很快就理解了这个协议.因 ...
- Codeforces Round div.2 C
Smiling & Weeping ----我对姑娘的喜欢,何止钟意二字 题目链接:Problem - C - Codeforces 自我分析:我感觉这是一道很有意义的题目,可以帮我们更好的理 ...
- Shell脚本中文英文多语言国际化和命令行批处理(bash sh cmd bat)中定义函数的简单写法
目录 命令行脚本参考 - bat 命令行脚本参考 - bash 值得学习的知识点 1. 识别终端使用的语言 2. 函数的编写 3. 获取用户的输入 4. bat文件老是乱码怎么办 有时候为了方便别人使 ...
- 树莓派4b装系统到运行 Blazor Linux 本地程序全记录
在Linux下运行gui程序,咱也是第一次做,属于是瞎子过河乱摸一通,写得有什么不对和可以优化的地方,希望各位看官斧正斧正. 1. 下载烧录器 https://www.raspberrypi.com/ ...
- Solution -「营业」「CF 527C」Glass Carving
Description Link. 有一个块 \(n\times m\) 的矩形,有 \(q\) 次操作,每次把矩形横 / 竖着切一刀,问切完后的最大矩形面积. Solution 一个不同于大多数人. ...
- 低功耗引擎 Cliptrix 有什么价值
在万物互联的时代,现代人已普遍接受电视.音箱等电器设备具备智能化能力,也是在这个趋势下,我们身边越来越多的iOT设备联网和交互成为刚需.但iot设备也面临到一些非常显著的痛点,例如iot设备的内存.处 ...