onlyoffice文档转换服务离线部署

实测onlyofficelibreoffice更好用。

  1. 基于docker部署,docker pull后再save一下,到内网中load。
  2. 从原始onlyoffice/documentserver镜像打进了相关中文字体,构建镜像时直接把相关字体文件copy进镜像即可,可直接用windows字体文件夹。
  3. 修改default.json文件,去掉了安全防护(https,token)。

Dockerfile

bash 复制代码
FROM onlyoffice/documentserver
LABEL authors="HuangChunfeng"

COPY ./fonts /usr/share/fonts/truetype/windows
# COPY ./default.json /etc/onlyoffice/documentserver/default.json

RUN fc-cache -fv

docker-compose

bash 复制代码
version: '3'

services:
  documentserver:
    image: hcf/onlyoffice-documentserver
    container_name: onlyoffice-documentserver
    restart: unless-stopped
    ports:
      - "7991:80"
    environment:
      - JWT_ENABLED=false
    volumes:
      - ./default.json:/etc/onlyoffice/documentserver/default.json

default.json

json 复制代码
{
	"statsd": {
		"useMetrics": false,
		"host": "localhost",
		"port": "8125",
		"prefix": "ds."
	},
	"aiSettings": {
		"actions": {
		},
		"models": [
		],
		"providers": {
		},
		"version": 3,
		"timeout": "30s",
		"allowedCorsOrigins": [
			"https://onlyoffice.github.io", "https://onlyoffice-plugins.github.io"
		],
		"pluginDir" : "../branding/info/ai"
	},
	"log": {
		"filePath": "",
		"options": {
			"replaceConsole": true
		}
	},
	"runtimeConfig": {
		"filePath": "",
		"cache": {
			"stdTTL": 300,
			"checkperiod": 60,
			"useClones": false
		}
	},
	"queue": {
		"type": "rabbitmq",
		"visibilityTimeout": 300,
		"retentionPeriod": 900
	},
	"email": {
		"smtpServerConfiguration": {
			"host": "localhost",
			"port": 587,
			"auth": {
				"user": "",
				"pass": ""
			}
		},
		"connectionConfiguration": {
			"disableFileAccess": false,
			"disableUrlAccess": false
		},
		"contactDefaults": {
			"from": "from@example.com",
			"to": "to@example.com"
		}
	},
	"notification": {
		"rules": {
			"licenseExpirationWarning": {
				"enable": false,
				"transportType": [
					"email"
				],
				"template": {
					"title": "%s Docs license expiration warning",
					"body": "Attention! Your license is about to expire on %s.\nUpon reaching this date, you will no longer be entitled to receive personal technical support and install new Docs versions released after this date."
				},
				"policies": {
					"repeatInterval": "1d"
				}
			},
			"licenseExpirationError": {
				"enable": false,
				"transportType": [
					"email"
				],
				"template": {
					"title": "%s Docs license expiration warning",
					"body": "Attention! Your license expired on %s.\nYou are no longer entitled to receive personal technical support and install new Docs versions released after this date.\nPlease contact sales@onlyoffice.com to discuss license renewal."
				},
				"policies": {
					"repeatInterval": "1d"
				}
			},
			"licenseLimitEdit": {
				"enable": false,
				"transportType": [
					"email"
				],
				"template": {
					"title": "%s Docs license connection limit warning",
					"body": "Attention! You have reached %s%% of the %s limit set by your license."
				},
				"policies": {
					"repeatInterval": "1h"
				}
			},
			"licenseLimitLiveViewer": {
				"enable": false,
				"transportType": [
					"email"
				],
				"template": {
					"title": "%s Docs license connection limit warning",
					"body": "Attention! You have reached %s%% of the live viewer %s limit set by your license."
				},
				"policies": {
					"repeatInterval": "1h"
				}
			}
		}
	},
	"storage": {
		"name": "storage-fs",
		"fs": {
			"folderPath": "",
			"urlExpires": 900,
			"secretString": "verysecretstring"
		},
		"region": "",
		"endpoint": "http://localhost/s3",
		"bucketName": "cache",
		"storageFolderName": "files",
		"cacheFolderName": "data",
		"urlExpires": 604800,
		"accessKeyId": "",
		"secretAccessKey": "",
		"sslEnabled": false,
		"s3ForcePathStyle": true,
		"externalHost": "",
		"useDirectStorageUrls": true
	},
	"persistentStorage": {
	},
	"rabbitmq": {
		"url": "amqp://localhost:5672",
		"socketOptions": {},
		"exchangepubsub": {
			"name": "ds.pubsub",
			"options": {
				"durable": true
			}
		},
		"queuepubsub": {
			"name": "",
			"options": {
				"autoDelete": true,
				"exclusive": true,
				"arguments": {
					"x-queue-type": "classic"
				}
			}
		},
		"queueconverttask": {
			"name": "ds.converttask6",
			"options": {
				"durable": true,
				"maxPriority": 6,
				"arguments": {
					"x-queue-type": "classic"
				}
			}
		},
		"queueconvertresponse": {
			"name": "ds.convertresponse",
			"options": {
				"durable": true,
				"arguments": {
					"x-queue-type": "classic"
				}
			}
		},
		"exchangeconvertdead": {
			"name": "ds.exchangeconvertdead",
			"options": {
				"durable": true
			}
		},
		"queueconvertdead": {
			"name": "ds.convertdead",
			"options": {
				"durable": true,
				"arguments": {
					"x-queue-type": "classic"
				}
			}
		},
		"queuedelayed": {
			"name": "ds.delayed",
			"options": {
				"durable": true,
				"arguments": {
					"x-queue-type": "classic"
				}
			}
		}
	},
	"activemq": {
		"connectOptions": {
			"port": 5672,
			"host": "localhost",
			"reconnect": false
		},
		"queueconverttask": "ds.converttask",
		"queueconvertresponse": "ds.convertresponse",
		"queueconvertdead": "ActiveMQ.DLQ",
		"queuedelayed": "ds.delayed",
		"topicpubsub": "ds.pubsub"
	},
	"dnscache": {
		"enable" : true,
		"ttl" : 300,
		"cachesize" : 1000
	},
	"openpgpjs": {
		"config": {
		},
		"encrypt": {
			"passwords": ["verysecretstring"]
		},
		"decrypt": {
			"passwords": ["verysecretstring"]
		}
	},
	"aesEncrypt": {
		"config": {
			"keyByteLength": 32,
			"saltByteLength": 64,
			"initializationVectorByteLength": 16,
			"iterationsByteLength": 5
		},
		"secret": "verysecretstring"
	},
	"bottleneck": {
		"getChanges": {
		}
	},
	"win-ca": {
		"inject": "+"
	},
	"wopi": {
		"enable": false,
		"host" : "",
		"htmlTemplate" : "../../web-apps/apps/api/wopi",
		"wopiZone" : "external-http",
		"favIconUrlWord" : "/web-apps/apps/documenteditor/main/resources/img/favicon.ico",
		"favIconUrlCell" : "/web-apps/apps/spreadsheeteditor/main/resources/img/favicon.ico",
		"favIconUrlSlide" : "/web-apps/apps/presentationeditor/main/resources/img/favicon.ico",
		"favIconUrlPdf" : "/web-apps/apps/pdfeditor/main/resources/img/favicon.ico",
		"favIconUrlDiagram" : "/web-apps/apps/visioeditor/main/resources/img/favicon.ico",
		"fileInfoBlockList" : ["FileUrl"],
		"pdfView": ["djvu", "xps", "oxps"],
		"pdfEdit": ["pdf"],
		"forms": ["pdf"],
		"wordView": ["doc", "dotm", "dot", "fodt", "ott", "rtf", "mht", "mhtml", "html", "htm", "xml", "epub", "fb2", "sxw", "stw", "wps", "wpt", "pages", "docxf", "oform", "hwp", "hwpx", "md"],
		"wordEdit": ["docx", "dotx", "docm", "odt", "txt"],
		"cellView": ["xls", "xltm", "xlt", "fods", "ots", "sxc", "xml", "et", "ett", "numbers"],
		"cellEdit": ["xlsx", "xlsb", "xltx", "xlsm", "ods", "csv"],
		"slideView": ["ppt", "ppsx", "ppsm", "pps", "potm", "pot", "fodp", "otp", "sxi", "dps", "dpt", "key", "odg"],
		"slideEdit": ["pptx", "potx", "pptm", "odp"],
		"diagramView": ["vsdx", "vstx", "vssx", "vsdm", "vstm", "vssm"],
		"diagramEdit": [],
		"publicKey": "",
		"modulus": "",
		"exponent": 65537,
		"privateKey": "",
		"publicKeyOld": "",
		"modulusOld": "",
		"exponentOld": 65537,
		"privateKeyOld": "",
		"refreshLockInterval": "10m",
		"dummy" : {
			"enable": false,
			"sampleFilePath": ""
		}
	},
	"tenants": {
		"baseDir": "",
		"baseDomain": "",
		"filenameConfig": "config.json",
		"filenameSecret": "secret.key",
		"filenameLicense": "license.lic",
		"defaultTenant": "localhost",
		"cache" : {
			"stdTTL": 300,
			"checkperiod": 60,
			"useClones": false
		}
	},
	"externalRequest": {
		"directIfIn" : {
			"allowList": [],
			"jwtToken": true
		},
		"action": {
			"allow": true,
			"blockPrivateIP": true,
			"proxyUrl": "",
			"proxyUser": {
				"username": "",
				"password": ""
			},
			"proxyHeaders": {
			}
		}
	},
	"services": {
		"CoAuthoring": {
			"server": {
				"port": 8000,
				"workerpercpu": 1,
				"mode": "development",
				"limits_tempfile_upload": 104857600,
				"limits_image_size": 26214400,
				"limits_image_download_timeout": {
					"connectionAndInactivity": "2m",
					"wholeCycle": "2m"
				},
				"callbackRequestTimeout": {
					"connectionAndInactivity": "10m",
					"wholeCycle": "10m"
				},
				"healthcheckfilepath": "../public/healthcheck.docx",
				"savetimeoutdelay": 5000,
				"edit_singleton": false,
				"forgottenfiles": "forgotten",
				"forgottenfilesname": "output",
				"maxRequestChanges": 20000,
				"openProtectedFile": true,
				"isAnonymousSupport": true,
				"editorDataStorage": "editorDataMemory",
				"editorStatStorage": "",
				"assemblyFormatAsOrigin": true,
				"newFileTemplate" : "../../document-templates/new",
				"downloadFileAllowExt": ["pdf", "xlsx"],
				"tokenRequiredParams": true,
				"forceSaveUsingButtonWithoutChanges": false
			},
			"requestDefaults": {
				"headers": {
					"User-Agent": "Node.js/6.13",
					"Connection": "Keep-Alive"
				},
				"rejectUnauthorized": true
			},
			"autoAssembly": {
				"enable": false,
				"interval": "5m",
				"step": "1m"
			},
			"utils": {
				"utils_common_fontdir": "null",
				"utils_fonts_search_patterns": "*.ttf;*.ttc;*.otf",
				"limits_image_types_upload": "jpg;jpeg;jpe;png;gif;bmp;svg;tiff;tif"
			},
			"sql": {
				"type": "postgres",
				"tableChanges": "doc_changes",
				"tableResult": "task_result",
				"dbHost": "localhost",
				"dbPort": 5432,
				"dbName": "onlyoffice",
				"dbUser": "onlyoffice",
				"dbPass": "onlyoffice",
				"charset": "utf8",
				"connectionlimit": 10,
				"max_allowed_packet": 1048575,
				"pgPoolExtraOptions": {
					"idleTimeoutMillis": 30000,
					"maxLifetimeSeconds ": 60000,
					"statement_timeout ": 60000,
					"query_timeout  ": 60000,
					"connectionTimeoutMillis": 60000
				},
				"damengExtraOptions": {
					"columnNameUpperCase": false,
					"columnNameCase": "lower",
					"connectTimeout": 60000,
					"loginEncrypt": false,
					"localTimezone": 0,
					"poolTimeout": 60,
					"socketTimeout": 60000,
					"queueTimeout": 60000
				},
				"oracleExtraOptions": {
					"connectTimeout": 60
				},
				"msSqlExtraOptions": {
					"options": {
						"encrypt": false,
						"trustServerCertificate": true
					},
					"pool": {
						"idleTimeoutMillis": 30000
					}
				},
				"mysqlExtraOptions": {
					"connectTimeout": 60000,
					"queryTimeout": 60000
				}
			},
			"redis": {
				"name": "redis",
				"prefix": "ds:",
				"host": "127.0.0.1",
				"port": 6379,
				"options": {},
				"optionsCluster": {},
				"iooptions": {
					"lazyConnect": true
				},
				"iooptionsClusterNodes": [
				],
				"iooptionsClusterOptions": {
					"lazyConnect": true
				}
			},
			"pubsub": {
				"maxChanges": 1000
			},
			"expire": {
				"saveLock": 60,
				"presence": 300,
				"locks": 604800,
				"changeindex": 86400,
				"lockDoc": 30,
				"message": 86400,
				"lastsave": 604800,
				"forcesave": 604800,
				"forcesaveLock": 5000,
				"saved": 3600,
				"documentsCron": "0 */2 * * * *",
				"files": 86400,
				"filesCron": "00 00 */1 * * *",
				"filesremovedatonce": 100,
				"sessionidle": "1h",
				"sessionabsolute": "30d",
				"sessionclosecommand": "2m",
				"pemStdTTL": "1h",
				"pemCheckPeriod": "10m",
				"updateVersionStatus": "5m",
				"monthUniqueUsers": "1y"
			},
			"ipfilter": {
				"rules": [{"address": "*", "allowed": true}],
				"useforrequest": false,
				"errorcode": 403
			},
			"request-filtering-agent" : {
				"allowPrivateIPAddress": true,
				"allowMetaIPAddress": true
			},
			"secret": {
				"browser": {"string": "secret", "file": ""},
				"inbox": {"string": "secret", "file": ""},
				"outbox": {"string": "secret", "file": ""},
				"session": {"string": "secret", "file": ""}
			},
			"token": {
				"enable": {
					"browser": false,
					"request": {
						"inbox": false,
						"outbox": false
					}
				},
				"browser": {
					"secretFromInbox": true
				},
				"inbox": {
					"header": "Authorization",
					"prefix": "Bearer ",
					"inBody": false
				},
				"outbox": {
					"header": "Authorization",
					"prefix": "Bearer ",
					"algorithm": "HS256",
					"expires": "5m",
					"inBody": false,
					"urlExclusionRegex": ""
				},
				"session": {
					"algorithm": "HS256",
					"expires": "30d"
				},
				"verifyOptions": {
					"clockTolerance": 60
				}
			},
			"plugins": {
				"uri": "/sdkjs-plugins",
				"autostart": []
			},
			"themes": {
				"uri": "/web-apps/apps/common/main/resources/themes"
			},
			"editor":{
				"spellcheckerUrl": "",
				"reconnection":{
					"attempts": 50,
					"delay": "2s"
				},
				"binaryChanges": false,
				"websocketMaxPayloadSize": "1.5MB",
				"maxChangesSize": "150MB"
			},
			"sockjs": {
				"sockjs_url": "",
				"disable_cors": true,
				"websocket": true
			},
			"socketio": {
				"connection": {
					"path": "/doc/",
					"serveClient": false,
					"pingTimeout": 20000,
					"pingInterval": 25000,
					"maxHttpBufferSize": 1e8
				}
			},
			"callbackBackoffOptions": {
				"retries": 3,
				"timeout":{
					"factor": 2,
					"minTimeout": 1000,
					"maxTimeout": 2147483647,
					"randomize": false
				},
				"httpStatus": "429,500-599"
			}
		}
	},
	"license" : {
		"license_file": "",
		"warning_limit_percents": 70,
		"packageType": 0,
		"warning_license_expiration": "30d"
	},
	"FileConverter": {
		"converter": {
			"maxDownloadBytes": 104857600,
			"downloadTimeout": {
				"connectionAndInactivity": "2m",
				"wholeCycle": "2m"
			},
			"downloadAttemptMaxCount": 3,
			"downloadAttemptDelay": 1000,
			"maxprocesscount": 1,
			"fontDir": "null",
			"presentationThemesDir": "null",
			"x2tPath": "null",
			"docbuilderPath": "null",
			"args": "",
			"spawnOptions": {},
			"errorfiles": "",
			"streamWriterBufferSize": 8388608,
			"maxRedeliveredCount": 2,
			"inputLimits": [
				{
				"type": "docx;dotx;docm;dotm",
				"zip": {
					"uncompressed": "50MB",
					"template": "*.xml"
				}
				},
				{
				"type": "xlsx;xltx;xlsm;xltm",
				"zip": {
					"uncompressed": "300MB",
					"template": "*.xml"
				}
				},
				{
				"type": "pptx;ppsx;potx;pptm;ppsm;potm",
				"zip": {
					"uncompressed": "50MB",
					"template": "*.xml"
				}
				}
			]
		}
	}
}

Python调用

bash 复制代码
import hashlib
import xml.etree.ElementTree as ET

# import jwt  # pip install pyjwt
import requests

# === 配置 ===
# jwt_secret = 'my_super_secret'  # 和 docker-compose 一致
documentserver_url = 'http://localhost:8080'
nginx_file_url = 'http://172.20.144.1:8081/uploads/test.doc'

# === 生成 JWT Token ===
# token = jwt.encode({}, jwt_secret, algorithm='HS256')

# print(f"JWT Token: {token}")

response = requests.get(nginx_file_url)

response.raise_for_status()

# === 转换请求 ===
payload = {
    "async": False,
    'key': hashlib.md5(response.content).hexdigest(),
    "filetype": "doc",
    "outputtype": "pdf",
    "title": "test.doc",
    "url": nginx_file_url,
    'pdfa': True
}

headers = {
    "Content-Type": "application/json",
    # "Authorization": f"Bearer {token}"
}

# 调用 ConvertService
res = requests.post(f'{documentserver_url}/ConvertService.ashx', headers=headers, json=payload)
print(res.text)
node = ET.fromstring(res.text).find('FileUrl')
if node is not None:
    print(f"转换成功,结果文件:{node.text}")
else:
    print("转换失败")
相关推荐
Chris_12193 小时前
Halcon学习笔记-Day6进阶:工业级视觉系统核心技术详解
人工智能·python·深度学习·halcon
飞鸟真人3 小时前
关于python -m http.server的一些安全问题
python·安全·http
tjjucheng4 小时前
小程序定制开发哪家性价比高
python
No0d1es4 小时前
2025年12月 GESP CCF编程能力等级认证Python六级真题
python·青少年编程·gesp·ccf·六级
亮子AI4 小时前
【Python】比较两个cli库:Click vs Typer
开发语言·python
CappuccinoRose4 小时前
流计算概述
python·flink·流计算·数据流·pyflink
Dragon水魅4 小时前
Fandom Wiki 网站爬取文本信息踩坑实录
爬虫·python
Darkershadow4 小时前
蓝牙学习之unprovision beacon
python·学习·ble
小龙在山东5 小时前
基于 plumbum 跨平台执行Shell脚本
python