关于linux服务上部署ppt等win的相关应用

知而不行,只是未知。 ---王阳明-
时间:2026年3月4日

最近做项目,遇到PPT转图片的服务,查出来的都是基于win32等win相关组件完成这件事情。

后面想了想,有没有office online 可以调用,查着查着就找到了 officeonly

安装

很简单,docker 一键部署。下面是 docker-compose.yml

services:
  onlyoffice:
    image: onlyoffice/documentserver
    container_name: onlyoffice
    ports:
        - '88:80'
    environment:
      TZ: 'Asia/Shanghai'
      JWT_ENABLED: 'false'
      # 添加这行,允许私有 IP 访问
      ALLOW_PRIVATE_IP: 'true'
    extra_hosts:
      - "fileserver:192.168.31.234"
    volumes:
      - './logs:/var/log/onlyoffice'
      - './data:/var/www/onlyoffice/Data'
      - './lib:/var/lib/onlyoffice'
      - './db:/var/lib/postgresql'
      # 挂载自定义配置文件
      - './local-production-linux.json:/etc/onlyoffice/documentserver/local-production-linux.json'
      - './default.json:/etc/onlyoffice/documentserver/default.json:ro'
  • yml 中 fileserver 记得要修改成自己服务端所在的 IP

挂载的文件有两个:default.jsonlocal-production-linux.json, 如下:

  1. default.json
{
  "adminPanel": {
    "port": 9000
  },
  "statsd": {
    "useMetrics": false,
    "host": "localhost",
    "port": "8125",
    "prefix": "ds."
  },
  "aiSettings": {
    "actions": {},
    "models": [],
    "providers": {},
    "version": 3,
    "timeout": "5m",
    "allowedCorsOrigins": ["https://onlyoffice.github.io", "https://onlyoffice-plugins.github.io"],
    "proxy": ""
  },
  "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 %s 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 %s 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",
    "commandOptions": {
      "s3": {
        "putObject": {},
        "getObject": {},
        "copyObject": {
          "MetadataDirective": "COPY"
        },
        "listObjects": {
          "MaxKeys": 1000
        },
        "deleteObject": {}
      },
      "az": {
        "uploadData": {},
        "uploadStream": {},
        "download": {},
        "syncCopyFromURL": {},
        "listBlobsFlat": {
          "maxPageSize": 1000
        },
        "deleteBlob": {}
      }
    },
    "urlExpires": 604800,
    "accessKeyId": "",
    "secretAccessKey": "",
    "sslEnabled": false,
    "s3ForcePathStyle": true,
    "externalHost": "",
    "useDirectStorageUrls": false
  },
  "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": [],
    "pdfEdit": [],
    "forms": [],
    "wordView": [],
    "wordEdit": [],
    "cellView": [],
    "cellEdit": [],
    "slideView": [],
    "slideEdit": [],
    "diagramView": [],
    "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": false,
      "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",
        "documentFormatsFile": "../../document-formats/onlyoffice-docs-formats.json",
        "downloadFileAllowExt": ["pdf", "xlsx"],
        "tokenRequiredParams": true,
        "forceSaveUsingButtonWithoutChanges": false
      },
      "requestDefaults": {
        "headers": {
          "User-Agent": "Node.js/6.13",
          "Connection": "Keep-Alive"
        },
        "rejectUnauthorized": false,
        "privateIP": true,
        "privateNetwork": true,
        "anyIP": 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;webp;heic;heif;avif",
        "limits_document_types_upload": "xlsx"
      },
      "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": {
          "thin": true,
          "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": false
      },
      "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",
      "signingKeyStorePath": "",
      "signing": {
        "keyStorePath": "",
        "meta": {
          "reason": "",
          "name": "",
          "location": "",
          "contactInfo": ""
        },
        "awsKms": {
          "endpoint": "",
          "keyId": "",
          "accessKeyId": "",
          "secretAccessKey": ""
        },
        "csc": {
          "baseUrl": "",
          "tokenUrl": "",
          "clientId": "",
          "clientSecret": "",
          "grantType": "",
          "clientAuth": "",
          "tokenBodyFormat": "",
          "username": "",
          "password": "",
          "credentialId": "",
          "clientData": "",
          "scope": "service",
          "audience": ""
        }
      },
      "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"
          }
        },
        {
          "type": "vsdx;vstx;vssx;vsdm;vstm;vssm",
          "zip": {
            "uncompressed": "50MB",
            "template": "*.xml"
          }
        }
      ]
    }
  }
}
  1. local-production-linux.json
{
  "services": {
    "CoAuthoring": {
      "server": {
        "allowPrivateIPAddresses": true
      }
    }
  }
}

使用

image

注意: 必须要有 header

{
    "Accept": "application/json",
    "Content-Type": "application/json;charset=UTF-8"
}

参考:

【onlyoffice中文指南】13-转换API接口(收藏转载)

注意:

在接口调用的时候,需要再传递一个参数 key:

{
    "url": "http://192.168.0.103:8001/api/v1/static/upload/2026/03/05/dev_20260305111157A135.pptx",
    "outputtype": "pdf",
    "filetype": "pptx",
    "title": "dev.pptx",
    "async": false,
    "key": "d8d446e8951448578d0ab7bc5a143be6"
}

因为 officeonly 为了提高性能,会缓存转换结果。如果接口请求中的文档标识(Key)或缓存ID没有正确更新,服务端会直接返回之前缓存的PDF文件,导致“所有文件都变成同一个PDF”。

这个 key 一般是一个 MD5 哈希值,长度 32 位,使用 uuid.uuid4().hex 生成即可。

posted @ 2026-03-04 20:49  shyNi  阅读(70)  评论(0)    收藏  举报