经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Docker » 查看文章
基于WPSOffice+Pywpsrpc构建Docker镜像,实现文档转换和在线预览服务
来源:cnblogs  作者:codest  时间:2023/12/8 11:50:45  对本文有异议

背景

产品功能需要实现标准文档的在线预览功能,由于DOC文档没办法直接通过浏览器打开预览,需要提前转换为PDF文档或者HTML页面。

经过测试发现DOC转为HTML页面后文件体积较大,而且生成的静态资源文件较多,需要额外搭建Web容器存放,所以还是考虑转换为PDF格式文档。

 

选型

需求明确后就要考虑如何实现了,这里对比了开源文档转换工具例如:kkFileViewdocuments4jpoiopenofficeasposeSpire.Office等。

选型主要考虑以下几个方面:

1、转换为PDF文档后是否会失真,也就是和原DOC文档的格式还原度;

2、是否支持大文档,有些标准文档超过40MB用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

  1. yum -y install epel-release
  2. yum groupinstall "GNOME Desktop"
  3. systemctl isolate graphical.target
  4. systemctl set-default graphical.target
  5. yum install xrdp -y
  6. yum install tigervnc-server -y
  7. # 设置vnc访问密码
  8. vncpasswd root
  9. systemctl start xrdp
  10. 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

  1. git clone https://github.com/iamdh4/ttf-wps-fonts.git
  2. cd ttf-wps-fonts
  3. sudo sh install.sh
  4. 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、编译安装

  1. # 解压压缩包
  2. tar -zxvf Python-3.6.15.tgz
  3. # 进入文件夹
  4. cd Python-3.6.15
  5. # 配置安装位置
  6. ./configure prefix=/usr/local/python3
  7. # 安装
  8. make && make install
  9. # 建立软连接
  10. ln -s /usr/local/python3/bin/python3.6 /usr/bin/python3
  11. 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,操作如下:

  1. # 下载源码包
  2. wget http://www.openssl.org/source/openssl-1.1.1l.tar.gz
  3. # 编译安装
  4. mkdir /usr/local/ssl
  5. ./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl no-zlib
  6. make && make install
  7. echo "/usr/local/ssl/lib" >> /etc/ld.so.conf

测试是否安装好,ldconfig -v 显示出相关内容,并查看/usr/local/ssl目录下确实有安装好的文件

  1. # 回到Python源吗目录下
  2. make clean
  3. # 配置安装位置
  4. ./configure prefix=/usr/local/python3

修改Modules/Setup文件

  1. make && make install
  2. ln -s /usr/local/python3/bin/python3 /usr/local/bin/python3
  3. 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通过图形化界面安装,安装时会提示注册按提示信息操作即可

文档转换服务

  1. import traceback, uuid, os
  2. from flask import Flask, request, send_from_directory
  3. from pywpsrpc.rpcwpsapi import (createWpsRpcInstance, wpsapi)
  4. from pywpsrpc.common import (S_OK, QtApp)
  5. app = Flask(__name__)
  6. # 设置文件上传保存路径
  7. app.config['UPLOAD_FOLDER'] = '/tmp'
  8. # MAX_CONTENT_LENGTH设置上传文件的大小,单位字节
  9. app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024 * 1024
  10. formats = {
  11. "doc": wpsapi.wdFormatDocument,
  12. "docx": wpsapi.wdFormatXMLDocument,
  13. "rtf": wpsapi.wdFormatRTF,
  14. "html": wpsapi.wdFormatHTML,
  15. "pdf": wpsapi.wdFormatPDF,
  16. "xml": wpsapi.wdFormatXML,
  17. }
  18. class ConvertException(Exception):
  19. def __init__(self, text, hr):
  20. self.text = text
  21. self.hr = hr
  22. def __str__(self):
  23. return """Convert failed:
  24. Details: {}
  25. ErrCode: {}
  26. """.format(self.text, hex(self.hr & 0xFFFFFFFF))
  27. def convert_to(path, format, abort_on_fails=False):
  28. hr, rpc = createWpsRpcInstance()
  29. if hr != S_OK:
  30. raise ConvertException("Can't create the rpc instance", hr)
  31. hr, app = rpc.getWpsApplication()
  32. if hr != S_OK:
  33. raise ConvertException("Can't get the application", hr)
  34. try:
  35. # we don't need the gui
  36. app.Visible = False
  37. docs = app.Documents
  38. def _handle_result(hr):
  39. if abort_on_fails and hr != S_OK:
  40. raise ConvertException("convert_file failed", hr)
  41. hr = convert_file(path, docs, format)
  42. _handle_result(hr)
  43. except Exception as e:
  44. print(traceback.format_exc())
  45. app.Quit(wpsapi.wdDoNotSaveChanges)
  46. def convert_file(file, docs, format):
  47. hr, doc = docs.Open(file, ReadOnly=True)
  48. if hr != S_OK:
  49. return hr
  50. out_dir = os.path.dirname(os.path.realpath(file)) + "/out"
  51. os.makedirs(out_dir, exist_ok=True)
  52. # you have to handle if the new_file already exists
  53. new_file = out_dir + "/" + os.path.splitext(os.path.basename(file))[0] + "." + format
  54. ret = doc.SaveAs2(new_file, FileFormat=formats[format])
  55. # always close the doc
  56. doc.Close(wpsapi.wdDoNotSaveChanges)
  57. return ret
  58. @app.route("/convert", methods=["POST"])
  59. def do_convert():
  60. try:
  61. # 转换格式参数
  62. convert_format = request.form['format']
  63. # 获取文件参数
  64. file = request.files['file']
  65. # 文件后缀
  66. file_ext = file.filename.rsplit('.')[-1]
  67. file_name_uuid = str(uuid.uuid4())
  68. # UUID文件名
  69. file_name = file_name_uuid + "." + file_ext
  70. # 保存文件
  71. file.save(os.path.join(app.config['UPLOAD_FOLDER'], file_name))
  72. # 文件转换
  73. print("开始转换文档[%s]" % file_name)
  74. convert_to(os.path.join(app.config['UPLOAD_FOLDER'], file_name), convert_format, True)
  75. print("文档转换完成[%s]" % file_name)
  76. # 返回转换后的文件
  77. convert_file_name = file_name_uuid + "." + convert_format
  78. return send_from_directory(app.config['UPLOAD_FOLDER'] + '/out', convert_file_name, as_attachment=True)
  79. except Exception as e:
  80. print('文档转换时发生错误')
  81. print(traceback.format_exc())
  82. return {"success": False}
  83. if __name__ == "__main__":
  84. app.run(host="0.0.0.0", port=9000)

使用mstsc远程登录CentOS桌面,执行启动脚本:

  1. #!/bin/bash
  2. set -e
  3. export PATH=$PATH:/opt/kingsoft/wps-office/office6
  4. export LD_LIBRARY_PATH=/opt/Qt5.12.12/5.12.12/gcc_64/lib
  5. python3 /root/converter.py

服务验证

1、远程桌面登录CentOS桌面后能够正常打开WPS软件,没有提示字体依赖错误;

2、文档转换接口测试:

  1. 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文档路径"'

 

原文链接:https://www.cnblogs.com/changxy-codest/p/17881350.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号