Ubuntu服务器使用LibreOffice转换DOCX到PDF时出现CalledProcessError错误
DOCX转PDF触发CalledProcessError(退出码77)的解决方案
问题现象
在Ubuntu服务器上通过HTML表单上传DOCX文件后,调用LibreOffice转换为PDF时,/add-document路径下触发CalledProcessError,执行命令返回非零退出状态码77。执行的错误命令如下:
['libreoffice', '--headless', '--convert-to', 'pdf', '/var/www/html/dev/media/documents/Lavender_Bay_Boatshed_Website_Testing_61gWm6r.docx', '--outdir', '/var/www/html/dev/media/documents/Lavender Bay Boatshed Website Testing.pdf']
对应Django视图代码
@login_required def add_document(request): title = "Add document" if request.method == 'POST': file = request.FILES.get('file') check = request.POST.get('check') subject = request.POST.get('subject') message = request.POST.get('message') print(request.POST) names = [] emails = [] for key in request.POST: if key.startswith('email_'): emails.append(request.POST[key]) elif key.startswith('name_'): names.append(request.POST[key]) print(emails) print(names) recipients = [] list_of_dicts = [{'email': email, 'name': name} for email, name in zip(emails, names)] if file: if (file.name.endswith('.jpg')) or (file.name.endswith('.png')): obj = Documents(document=file,name=file.name,user=request.user) obj.save() image = Image.open(obj.document.path) iml = image.convert('RGB') folder = r'C:\Users\admin\Desktop\projects\Document-sign\media\documents' path = os.path.join(folder, file.name.split('.')[0] + '.pdf') os.remove(obj.document.path) iml.save(path) obj.document = f"documents/{file.name.split('.')[0]}.pdf" obj.save() os.remove(obj.document.path) if check: request.session['check'] = False return redirect('sign_document') else: recipients.append({'emails':list_of_dicts,'subject':subject,'message':message}) request.session['recipients'] = recipients request.session['check'] = True return redirect('make_envelope') elif file.name.endswith('.docx'): obj = Documents(document=file, name=file.name, user=request.user) obj.save() # Define paths path = os.path.join(settings.MEDIA_ROOT, 'documents') input_path = obj.document.path # Run LibreOffice conversion try: result = subprocess.run( ['libreoffice', '--headless', '--convert-to', 'pdf', input_path, '--outdir', path], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) print(result.stdout) print(result.stderr) except subprocess.CalledProcessError as e: print("Error occurred:", e.stderr) raise # Remove the original DOCX file os.remove(input_path) # Update the document path to the converted PDF obj.document = f"documents/{file.name.split('.')[0]}.pdf" obj.save() if check: request.session['check'] = False return redirect('sign_document') else: recipients.append({'emails':list_of_dicts,'subject':subject,'message':message}) request.session['recipients'] = recipients request.session['check'] = True return redirect('make_envelope') else: obj = Documents(document=file,name=file.name,user=request.user) obj.save() if check: request.session['check'] = False return redirect('sign_document') else: recipients.append({'emails':list_of_dicts,'subject':subject,'message':message}) print(recipients) request.session['recipients'] = recipients request.session['check'] = True return redirect('make_envelope') context = {'title':title} return render(request, 'myapp/add_document.html',context=context)
解决步骤
- 修复
--outdir参数错误:错误命令中--outdir后跟随的是PDF文件名而非目录,需确保该参数指向存储PDF的目录(代码中path变量已为正确目录,需排查是否有其他逻辑篡改了该值)。 - 安装无头模式依赖:退出码77通常是LibreOffice缺少显示依赖导致,执行以下命令安装必要组件:
修改转换命令,通过sudo apt-get install libreoffice libreoffice-writer xvfbxvfb-run运行LibreOffice以避免无头模式显示问题:result = subprocess.run( ['xvfb-run', '--auto-servernum', 'libreoffice', '--headless', '--convert-to', 'pdf', input_path, '--outdir', path], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) - 修正文件权限:确保Django运行用户(通常为
www-data)对媒体目录有读写权限:sudo chown -R www-data:www-data /var/www/html/dev/media/documents sudo chmod -R 755 /var/www/html/dev/media/documents - 路径转义处理:对含空格的文件路径进行转义,避免命令解析错误:
import shlex result = subprocess.run( ['xvfb-run', '--auto-servernum', 'libreoffice', '--headless', '--convert-to', 'pdf', shlex.quote(input_path), '--outdir', shlex.quote(path)], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) - 清理残留进程:LibreOffice无头模式可能残留进程导致转换失败,可在转换前清理:
subprocess.run(['pkill', '-f', 'libreoffice'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
内容的提问来源于stack exchange,提问作者vaibhav girase
相关产品推荐
相关产品推荐

