αžšαžΌαž”αž˜αž“αŸ’αž uWSGIαŸ– αž€αžΆαžšαž”αŸ†αž”αŸ’αž›αŸ‚αž„αž―αž€αžŸαžΆαžšαžŠαŸ„αž™αž”αŸ’αžšαžΎ LibreOffice

αžŠαžΎαž˜αŸ’αž”αžΈαžšαŸ€αž”αž…αŸ†αž€αžΆαžšαž”αž˜αŸ’αž›αŸ‚αž„αž―αž€αžŸαžΆαžšαž™αžΎαž„αžαŸ’αžšαžΌαžœαž€αžΆαžš LibreOffice, uwsgi-python, pylokit ΠΈ webob. αž’αŸ’αž“αž€αž€αŸαž’αžΆαž…αž”αŸ’αžšαžΎαž•αž„αžŠαŸ‚αžšαŸ” αžšαž½αž…αžšαžΆαž›αŸ‹. αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž“αŸαŸ‡αž‚αžΊαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžαŸ‚αž”αžΎαž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸ uWSGI αž αžΎαž™αžŠαžΎαž˜αŸ’αž”αžΈαž—αŸ’αž‡αžΆαž”αŸ‹αž‘αŸ…αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸ uWSGI αž™αžΎαž„αž“αžΉαž„αž”αŸ’αžšαžΎ nginx.

αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ uWSGI αžŸαžΆαž˜αž‰αŸ’αž‰αž”αŸ†αž•αž»αžαž“αŸ…αž€αŸ’αž“αž»αž„ python αž˜αžΆαž“αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž˜αž»αžαž„αžΆαžšαžŠαŸ‚αž›αž˜αžΆαž“αž’αžΆαž‚αž»αž™αž˜αŸ‰αž„αŸ‹αž–αžΈαžš αž”αžšαž·αžŸαŸ’αžαžΆαž“ αž“αž·αž„ start_response

import os       # ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ
import pylokit  # Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅
import tempfile # Π½Π°ΠΌ
import webob    # ΠΌΠΎΠ΄ΡƒΠ»ΠΈ

office = pylokit.Office('/usr/lib/libreoffice/program') # Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΡƒ LibreOffice ΠΏΠΎ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΌΡƒ ΠΏΡƒΡ‚ΠΈ

def application(environ, start_response): # функция для uWSGI
    request = webob.Request(environ) # ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ запрос ΠΈΠ· окруТСния
    file = request.POST['file'] # Ρ„Π°ΠΉΠ» для прСобразования пСрСдаётся Ρ‡Π΅Ρ€Π΅Π· multipart/form-data с ΠΈΠΌΠ΅Π½Π΅ΠΌ file
    filename, extension = os.path.splitext(file.filename) # ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ имя ΠΈ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅
    with tempfile.NamedTemporaryFile(suffix=extension) as inp, tempfile.NamedTemporaryFile(suffix='.%s' % request.path.split('/')[-1]) as out: # создаём ΠΎΠ΄ΠΈΠ½ Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» с Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ΠΌ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π° ΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠΉ Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» с Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ΠΌ ΠΈΠ· окончания запроса (для совмСстимости с unoconv-api)
        inp.write(file.file.read()) # записываСм содСрТимоС ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π° Π² ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ»
        inp.flush() # (Ρ‚.ΠΊ. LibreOfficeKit ΠΏΠΎΡ‡Π΅ΠΌΡƒ-Ρ‚ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ с Ρ„Π°ΠΉΠ»Π°ΠΌΠΈ)
        with office.documentLoad(inp.name) as doc: # Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» 
            doc.saveAs(out.name) # экспортируСм Π·Π°Π³Ρ€ΡƒΠΆΠ΅Π½Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» Π² Π΄Ρ€ΡƒΠ³ΠΎΠΉ Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» (Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ бСрётся ΠΈΠ· Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ)
            with open(out.name, 'rb') as out2: # ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°Π΅ΠΌ Π΄Ρ€ΡƒΠ³ΠΎΠΉ Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ»
                response = webob.Response(body=out2.read()) # создаём Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΈΠ· чтСния Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π°
                return response(environ, start_response) # ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌ Π΅Π³ΠΎ

αž’αŸ’αž“αž€αž€αŸαž’αžΆαž…αž”αž“αŸ’αžαŸ‚αž˜αž€αžΆαžšαžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž€αŸ†αž αž»αžŸαž•αž„αžŠαŸ‚αžšαŸ”

αž€αžΆαžšαž”αŸ†αž”αŸ’αž›αŸ‚αž„αž―αž€αžŸαžΆαžš odt αž‘αŸ†αž–αŸαžšαžαŸ‚αž˜αž½αž™αžŸαžΆαž€αž›αŸ’αž”αž„αž‘αŸ…αž‡αžΆ pdf αž‚αžΊαž›αžΏαž“αž‡αžΆαž„αž”αŸ’αžšαž αŸ‚αž› 1,5 αžŠαž„αž”αžΎαž’αŸ€αž”αž“αžΉαž„ unoconv-api.

αž”αŸ’αžšαž—αž–: www.habr.com

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžαž·αž™αŸ„αž”αž›αŸ‹