COM问题发生在我在IIS上运行我的Flask代码时,当使用docx转换为pdf时。

huangapple go评论73阅读模式
英文:

COM problem when i run my flask code on IIS when using docx to pdf conversion

问题

你的Flask应用包含一个函数,用于创建docx文档,然后将其转换为PDF。当在本地运行代码时,一切都正常,PDF文档被创建。但当将应用部署到IIS上,并使用fastcgi模块时,虽然创建docx文档没有问题,但由于错误而无法创建PDF文档。以下是创建docx文档并使用docx2pdf库进行转换的函数:

def CreateApplication(file, replacements, serialnum):
    document = Document(file)
    for para in document.paragraphs:
        # 迭代段落中的文本运行
        for run in para.runs:
            # 检查运行的文本是否是替换字典中的关键字
            if run.text in replacements:
                # 用替换的内容替换关键字,并保持样式
                run.text = replacements[run.text]
    for table in document.tables:
        for row in table.rows:
            for cell in row.cells:
                for paragraph in cell.paragraphs:
                    for run in paragraph.runs:
                        for keyword, value in replacements.items():
                            if keyword in run.text:
                                # 用值替换关键字
                                run.text = run.text.replace(keyword, value)
    document.save(f'files/{serialnum}/MainFiles/Application{serialnum}.docx')
    docx_output_path = f'files/{serialnum}/MainFiles/Application{serialnum}.docx'
    pdf_input_path = docx_output_path

    # 指定输出的.pdf文件路径
    pdf_output_path = os.path.splitext(pdf_input_path)[0] + '.pdf'

    # 将.docx文件转换为.pdf
    convert(pdf_input_path, pdf_output_path)

以下是如何从Flask中调用它的方式:

@app.route('/submitapplication/<serialnumber>', methods=['POST', 'GET'])
def submit(serialnumber):
    st = time.time()
    print('iam in')
    datacoming = request.get_json()
    print(datacoming)
    project_description = json.loads(datacoming)
    project_description['Statue_of_Project'] = 'Application pending'
    current_date = datetime.now()
    formatted_date = current_date.strftime("%Y-%m-%d")
    project_description['DateofApplication'] = formatted_date
    print(project_description)
    pidata = Search_in_Company(session['user'], session['password'], session['serverip'], session['companyid'])
    project_description.update(pidata)

    # 编写SQL代码将此字典上传到指定的行

    project_description['Project_Serial_Number'] = serialnumber

    # 使用线程在另一个线程中运行转换
    Application = threading.Thread(target=CreateApplication, args=('LPG application General.docx', project_description, serialnumber))
    Application.start()

    # 获取执行时间

    Update_case(session['user'], session['password'], session['serverip'], session['currentserial'], session['companyid'], project_description)
    et = time.time()
    elapsed_time = et - st
    print('Execution time:', elapsed_time, 'seconds')
    return jsonify({'url': url_for('home')})

当你尝试使用comtypes.client库时,出现了错误。使用docx2pdf库时也会出现类似的错误。请注意,你已经为Word和PDF赋予了默认应用程序池和IIS_IUSRS所需的权限。

错误信息是:

OSError: [WinError -2146959355] Server execution failed
pywintypes.com_error: (-2146959355, 'Server execution failed', None, None)

这个错误表明在服务器执行时发生了问题。可能是由于IIS上的权限问题,或者由于服务器环境与本地环境不同而引起的。你可能需要查看IIS和服务器上的权限设置,以确保代码可以正常执行。另外,确保你的服务器上已安装了所需的依赖项。

英文:

I have a flask app that contains a function to create a docx document then converts it to pdf, when i run the code on my local machine everything works fine and the pdf document is created but when i host the app on IIS on deployment machine with fastcgi module, it works fine and creates the docx document but doesn't create the pdf document due to an error, here is the function that creates docx document and converts to pdf using docx2pdf library:

def CreateApplication(file,replacements,serialnum):

    document=Document(file)
    for para in document.paragraphs:
        # Iterate through the runs in the paragraph
        for run in para.runs:
            # Check if the run text is a keyword in the replacements dictionary
            if run.text in replacements:
                # Replace the keyword with the replacement and maintain the style
                run.text = replacements[run.text]
    for table in document.tables:
        for row in table.rows:
            for cell in row.cells:
                for paragraph in cell.paragraphs:
                    for run in paragraph.runs:
                        for keyword, value in replacements.items():
                            if keyword in run.text:
                                # Replace the keyword with the value
                                run.text = run.text.replace(keyword, value)
    document.save(f&#39;files/{serialnum}/MainFiles/Application{serialnum}.docx&#39;)
    docx_output_path=f&#39;files/{serialnum}/MainFiles/Application{serialnum}.docx&#39;
    pdf_input_path = docx_output_path
    
    # Specify the path of the output .pdf file
    pdf_output_path = os.path.splitext(pdf_input_path)[0] + &#39;.pdf&#39;
    
    # Convert the .docx file to .pdf
    convert(pdf_input_path, pdf_output_path)

And here is how I call it from flask:

@app.route(&#39;/submitapplication/&lt;serialnumber&gt;&#39;,methods=[&#39;POST&#39;,&#39;GET&#39;])
def submit(serialnumber):
    st = time.time()
    print(&#39;iam in&#39;)
    datacoming=request.get_json()
    print(datacoming)
    project_describtion=json.loads(datacoming)
    project_describtion[&#39;Statue_of_Project&#39;]=&#39;Application pending&#39;
    current_date = datetime.now()
    formatted_date = current_date.strftime(&quot;%Y-%m-%d&quot;)
    project_describtion[&#39;DateofApplication&#39;] = formatted_date
    print(project_describtion)
    pidata = Search_in_Company(session[&#39;user&#39;], session[&#39;password&#39;], session[&#39;serverip&#39;], session[&#39;companyid&#39;])
    project_describtion.update(pidata)
    &#39;&#39;&#39;
    write sql code to upload this dictionary to its specified rows
    &#39;&#39;&#39;
    project_describtion[&#39;Project_Serial_Number&#39;]=serialnumber
    #CreateApplication(&#39;LPG application General.docx&#39;,project_describtion,serialnumber)

    #trying threading to run conversion in another thread
    Application=threading.Thread(target=CreateApplication,args=(&#39;LPG application General.docx&#39;,project_describtion,serialnumber))
    Application.start()


    # get the execution time


    Update_case(session[&#39;user&#39;],session[&#39;password&#39;],session[&#39;serverip&#39;],session[&#39;currentserial&#39;],session[&#39;companyid&#39;],project_describtion)
    et = time.time()
    elapsed_time = et - st
    print(&#39;Execution time:&#39;, elapsed_time, &#39;seconds&#39;)
    return jsonify({&#39;url&#39;: url_for(&#39;home&#39;)})

and here is the error that shows up when i tried comtypes.client libreary, a similer error shows up when i use docx2pdf library:

Exception on /submitapplication/JO-2023JL030039 [POST]
Traceback (most recent call last):
  File &quot;C:\Python\python311\Lib\site-packages\flask\app.py&quot;, line 2525, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;C:\Python\python311\Lib\site-packages\flask\app.py&quot;, line 1822, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;C:\Python\python311\Lib\site-packages\flask\app.py&quot;, line 1820, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;C:\Python\python311\Lib\site-packages\flask\app.py&quot;, line 1796, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;C:\inetpub\wwwroot\flpgproj\main.py&quot;, line 404, in submit
    CreateApplication(&#39;LPG application General.docx&#39;,project_describtion,serialnumber)
  File &quot;C:\inetpub\wwwroot\flpgproj\CreateFiles.py&quot;, line 136, in CreateApplication
    convert_to_pdf(pdf_input_path, pdf_output_path)
  File &quot;C:\inetpub\wwwroot\flpgproj\CreateFiles.py&quot;, line 35, in convert_to_pdf
    word=comtypes.client.CreateObject(&#39;Word.Application&#39;)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;C:\Python\python311\Lib\site-packages\comtypes\client\__init__.py&quot;, line 215, in CreateObject
    obj = comtypes.CoCreateInstance(clsid, clsctx=clsctx, interface=interface)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;C:\Python\python311\Lib\site-packages\comtypes\__init__.py&quot;, line 1264, in CoCreateInstance
    _ole32.CoCreateInstance(byref(clsid), punkouter, clsctx, byref(iid), byref(p))
  File &quot;_ctypes/callproc.c&quot;, line 1000, in GetResult
OSError: [WinError -2146959355] Server execution failed

and here is the exact same error that shows up when i use docx2pdf library, please note that i gave all required permissions to word and pdf to defaultapplicationpool and to iis_iusr:

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File &quot;C:\Python\python311\Lib\site-packages\flask\app.py&quot;, line 2525, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;C:\Python\python311\Lib\site-packages\flask\app.py&quot;, line 1822, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;C:\Python\python311\Lib\site-packages\flask\app.py&quot;, line 1820, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;C:\Python\python311\Lib\site-packages\flask\app.py&quot;, line 1796, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;C:\inetpub\wwwroot\flpgproj\main.py&quot;, line 404, in submit
    CreateApplication(&#39;LPG application General.docx&#39;,project_describtion,serialnumber)
  File &quot;C:\inetpub\wwwroot\flpgproj\CreateFiles.py&quot;, line 136, in CreateApplication
    convert(pdf_input_path, pdf_output_path)
  File &quot;C:\Python\python311\Lib\site-packages\docx2pdf\__init__.py&quot;, line 106, in convert
    return windows(paths, keep_active)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;C:\Python\python311\Lib\site-packages\docx2pdf\__init__.py&quot;, line 19, in windows
    word = win32com.client.Dispatch(&quot;Word.Application&quot;)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;C:\Python\python311\Lib\site-packages\win32com\client\__init__.py&quot;, line 117, in Dispatch
    dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch, userName, clsctx)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;C:\Python\python311\Lib\site-packages\win32com\client\dynamic.py&quot;, line 106, in _GetGoodDispatchAndUserName
    return (_GetGoodDispatch(IDispatch, clsctx), userName)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;C:\Python\python311\Lib\site-packages\win32com\client\dynamic.py&quot;, line 88, in _GetGoodDispatch
    IDispatch = pythoncom.CoCreateInstance(
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
pywintypes.com_error: (-2146959355, &#39;Server execution failed&#39;, None, None)

答案1

得分: 1

根据堆栈跟踪,您的库正在自动化 Word(在您的情况下来自 IIS)进行文件转换操作:

 File &quot;C:\inetpub\wwwroot\flpgproj\CreateFiles.py&quot;, line 35, in convert_to_pdf
    word=comtypes.client.CreateObject(&#39;Word.Application&#39;)

微软目前不建议,并不支持从不经交互的客户端应用程序或组件(包括 ASP、ASP.NET、DCOM 和 NT 服务)自动化 Microsoft Office 应用程序,因为在这种环境中运行 Office 可能表现出不稳定的行为和/或死锁。

如果您正在构建一个在服务器端上下文中运行的解决方案,您应该尝试使用已经为不经交互执行而设计的组件。或者,您可以尝试寻找允许至少部分代码在客户端运行的替代方法。如果您在服务器端解决方案中使用 Office 应用程序,该应用程序将缺少成功运行所需的许多功能。此外,您将冒着整体解决方案稳定性的风险。更多信息,请参阅 Considerations for server-side Automation of Office 文章。

如果您只处理开放的 XML 文档,您可以考虑使用 Open XML SDK,详细信息请参见 Welcome to the Open XML SDK 2.5 for Office。即使 SDK 不提供将文档转换为 PDF 文件格式的任何功能,您仍然可以找到基于 Open XML SDK 构建的解决方案(开源库),允许使用 PDF 文件格式导出/保存文档。

此外,您还可以搜索不需要在系统上安装 Word 的第三方组件/库,用于文件转换(设计用于服务器端执行)。

英文:

According to the stack-trace your libraries are automating Word (from IIS in your case) for the file conversion operations:

 File &quot;C:\inetpub\wwwroot\flpgproj\CreateFiles.py&quot;, line 35, in convert_to_pdf
    word=comtypes.client.CreateObject(&#39;Word.Application&#39;)

Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.

If you are building a solution that runs in a server-side context, you should try to use components that have been made safe for unattended execution. Or, you should try to find alternatives that allow at least part of the code to run client-side. If you use an Office application from a server-side solution, the application will lack many of the necessary capabilities to run successfully. Additionally, you will be taking risks with the stability of your overall solution. Read more about that in the Considerations for server-side Automation of Office article.

If you are dealing with open XML documents only you may consider using the Open XML SDK instead, see Welcome to the Open XML SDK 2.5 for Office for more information. Even if SDK doesn't provide anything for converting documents to the PDF file format, you may find solutions (open-source libraries) built on top of Open XML SDK that allows exporting/saving documents using the PDF file format.

Also you may search for third-party components/libraries that don't Word installed on the system for the file conversion (designed for the server-side execution).

huangapple
  • 本文由 发表于 2023年3月4日 08:02:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/75632816.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定