grpc 之 word2pdf使用

​ 做一个word转pdf的服务,采用grpc,使用libreoffice命令。

1.构建libreoffice镜像

FROM python:3.6

ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

RUN cd /etc/apt \
    && mv sources.list sources.list.bak \
    && echo "deb http://mirrors.aliyun.com/debian/ stretch main non-free contrib \
deb-src http://mirrors.aliyun.com/debian/ stretch main non-free contrib \
deb http://mirrors.aliyun.com/debian-security stretch/updates main \
deb-src http://mirrors.aliyun.com/debian-security stretch/updates main \
deb http://mirrors.aliyun.com/debian/ stretch-updates main non-free contrib \
deb-src http://mirrors.aliyun.com/debian/ stretch-updates main non-free contrib \
deb http://mirrors.aliyun.com/debian/ stretch-backports main non-free contrib \
deb-src http://mirrors.aliyun.com/debian/ stretch-backports main non-free contrib" > sources.list
RUN apt-get update
RUN apt-get install -y libreoffice
COPY ./ /root/
RUN mv /root/simsun.ttc /usr/share/fonts && mv /root/simhei.ttf /usr/share/fonts && cd /usr/share/fonts && fc-cache -fv
# docker build -t libreoffice .
  1. 采用python3.6镜像
  2. 使用阿里源
  3. 安装libreoffice
  4. 解决中文乱码 加入中文字体

2.grpc服务端、客户端

  1. 创建proto配置文件 然后编译

  2. 服务端与客户端 采用二进制 数据进行传输

  • 服务端

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Time    : 2019/7/9 0009 16:41
    # @File    : word2pdf_server_main.py
    # @author  : dfkai
    # @Software: PyCharm
    
    # python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. ./data.proto
    
    import os
    import pathlib
    import time
    import traceback
    import uuid
    from concurrent import futures
    
    import grpc
    
    from proto_py import word2pdf_pb2, word2pdf_pb2_grpc
    
    _ONE_DAY_IN_SECONDS = 60 * 60 * 24
    _HOST = os.environ.get("HOSTNAME", "localhost")
    _PORT = '8080'
    
    
    class FormatData(word2pdf_pb2_grpc.FormatDataServicer):
        def DoFormat(self, request, context):
            """
            proto 定义方法
            :param request:
            :param context:
            :return:
            """
            data = request.text
            doc_path, pdf_path, pdf_file_path = self.get_doc_pdf_path()
            with open(doc_path, "wb") as f:
                f.write(data)
            if self.word2pdf_linux(doc_path, pdf_path):
                try:
                    with open(pdf_file_path, "rb") as f:
                        pdf_data = f.read()
                except:
                    traceback.format_exc()
            else:
                pdf_data = b"fail"
            return word2pdf_pb2.Data(text=pdf_data)
    
        def get_doc_pdf_path(self):
            """
            获取文件路径
            :return:
            """
            baseDir = os.getcwd()
            p = pathlib.Path(baseDir)
            u_name = str(uuid.uuid4()).replace("-", "")
            doc_name = u_name + ".docx"
            pdf_name = u_name + ".pdf"
            pdf_path = p / f"filepath/pdf/"
            doc_path = p / f"filepath/doc/{doc_name}"
            pdf_file_path = p / f"filepath/pdf/{pdf_name}"
            print(doc_path, pdf_path, pdf_file_path)
            return rf"{doc_path}", rf"{pdf_path}", rf"{pdf_file_path}"
    
        def word2pdf_win(self, doc_path, pdf_path):
            """
            windows 生成
            :param doc_path:
            :param pdf_path:
            :return:
            """
            from win32com import client
            import pythoncom
            pythoncom.CoInitialize()
            # word = client.Dispatch("Word.Application")
            word = client.DispatchEx("Word.Application")
            worddoc = word.Documents.Open(doc_path)
            try:
                worddoc.SaveAs(pdf_path, FileFormat=17)
            except Exception as e:
                print(e)
                return False
            finally:
                worddoc.Close()
            return True
    
        def word2pdf_linux(self, doc_path, pdf_path):
            """
            linux 生成 pdf ,利用 libreoffice 命令
            :param doc_path:
            :param pdf_path:
            :return:
            """
            try:
                os.system(f"soffice --headless --invisible --convert-to pdf {doc_path} --outdir {pdf_path} ")
            except:
                traceback.format_exc()
                return False
            return True
    
    
    def serve():
        """
        rpc 服务
        :return:
        """
        grpcServer = grpc.server(futures.ThreadPoolExecutor(max_workers=4))
        word2pdf_pb2_grpc.add_FormatDataServicer_to_server(FormatData(), grpcServer)
        grpcServer.add_insecure_port(_HOST + ':' + _PORT)
        grpcServer.start()
        try:
            while True:
                time.sleep(_ONE_DAY_IN_SECONDS)
        except KeyboardInterrupt:
            grpcServer.stop(0)
    
    
    if __name__ == '__main__':
        serve()
    
    
  • 客户端

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Time    : 2019/7/9 0009 16:40
    # @File    : word2pdf_client_main.py
    # @author  : dfkai
    # @Software: PyCharm
    import traceback
    import grpc
    from proto_py import word2pdf_pb2, word2pdf_pb2_grpc
    
    _HOST = 'localhost'
    _PORT = '8080'
    
    
    def run():
        file_name = "test"
        doc_name = file_name + '.doc'
        conn = grpc.insecure_channel(_HOST + ':' + _PORT)
        client = word2pdf_pb2_grpc.FormatDataStub(channel=conn)
        with open(doc_name, "rb") as f:
            data = f.read()
        response = client.DoFormat(word2pdf_pb2.Data(text=data))
        if response.text == b"fail":
            # 发送消息 生成失败
            pass
        else:
            pdf_name = file_name + f'.pdf'
            try:
                with open(pdf_name, "wb") as f:
                    f.write(response.text)
            except:
                traceback.format_exc()
                # 发送消息 生成失败
            else:
                # 发送消息 生成成功
                pass
    
    
    if __name__ == '__main__':
        import time
        beg = time.time()
        run()
        end = time.time()
        print(end - beg)
    
    
  • proto配置文件

    syntax = "proto3";
    package example;
    service FormatData {
      rpc DoFormat(Data) returns (Data){}
    }
    message Data {
      bytes text = 1;
    }
    

    进入文件目录,构建命令:python -m grpc_tools.protoc -I. --python_out=./proto_py/ --grpc_python_out=./proto_py/ ./proto/word2pdf.proto

3.构建rpc服务端镜像

FROM libreoffice

ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

COPY ./ /root/
WORKDIR /root/word2pdfRPC
RUN pip3 install -i https://mirrors.aliyun.com/pypi/simple/ -r requirments.txt
EXPOSE 8080
CMD python server_main.py
# docker build -t word2pdf .
# docker run -d -p 8080:8080 -v /root/data/word2pdf/:/root/word2pdfRPC/filepath/ --name word2pdf word2pdf

  • reuirements.txt

    futures==3.1.1
    grpcio==1.22.0
    grpcio-tools==1.22.0
    protobuf==3.8.0
    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容