微信小程序开发怎么做/广西seo关键词怎么优化
文档转换是非常常用、非常有价值的功能,可以帮助我们处理多种文档类型。ONLYOFFICE 编辑器可以轻松地将文档转换为多种格式。在这篇博文中,我们会向您展示,如何构建在 ONLYOFFICE 转换 API 上运行的在线转换器。

关于 ONLYOFFICE 转换 API
使用文档转换服务,您可就各种类型的 Office 文档做转换:文本、表格、幻灯片、表单、PDF 和电子书。它帮助您基于文档和表格创建 PDF,将教科书转换为电子书,将演示文稿转换为图片文件,等等。ONLYOFFICE 支持 50 多种文件类型。
操作方法
我们的转换 API 通过“文档转换服务”运行。它是 ONLYOFFICE 文档服务器的一部分,支持我们将各种文档文件转换为合适的格式。
转换要分几个步骤进行:
- 用户选择一个要上传到“文档管理器”的文件。
- “文档管理器”将选定的文件上传到“文档存储服务”。
- “文档存储服务”通过使用“转化 API”将上传的文件发送到“文档转换服务”。
- “文档转换服务”将选定的文件转换为目标格式。
- “文档存储服务”下载转换后的文档文件。

“文档管理器”和“文档存储服务”是客户端和服务器端的工具,方便选择和存储文档供进一步转换。不过,我们的 web 应用会处理这些任务,这得益于我们正在构建的自定义转换器。
前提条件
我们的转换器基于 NodeJS。因此,对于这个项目,我们需要如下条件:
- ONLYOFFICE 文档服务器
- 安装了如下软件包的 NodeJS 应用:
– Express
– Axios
– Jsonwebtoken
我们会使用 Axios 包向 ONLYOFFICE 文档服务器发送一个 post 请求,并使用 Jsonwebtoken 包签署一个 JWT 令牌。从版本 7.2 开始,JWT 认证默认处于启用状态。
或者,您还可以通过另一个选项,在 JWT 认证停用的情况下运行 ONLYOFFICE 文档服务器镜像。为此,请在终端执行如下命令:
sudo docker run -i -t -d -p 80:80 -e JWT_ENABLED=false onlyoffice/documentserver
我们的转换器向 ONLYOFFICE 文档服务器发送的“post 请求”如下:
{"async": true,"filetype": fileType,"key": key, "outputtype": outputType,"title": `Converted Document.${outputType}`,"url": link }
- 在“accept”参数中,我们指定要接收 JSON 格式的响应。
- “async”参数指示该请求是异步请求。
- “fileType”参数指定我们要转换的原始文件的类型。
- “key”参数指定当前文件的唯一标识符 (UID)。
- “outputType”参数指定转换后的文件的格式。
- “title”参数包含转换后的文档的名称。
- “url”参数包含指向我们要转换的文件的链接。
“fileType”、“outputType”和“url”参数的值是从我们应用的客户端获取,存储在变量中。“key”参数的值也是随机生成,存储在变量中。
项目设置
将所需的包安装好后,我们前往“app.js”文件,将它们与“bodyParser”一起初始化,以处理“post 请求”数据。我们还创建了一个公开文件夹和一个视图引擎:
const express = require('express');
const app = express();
const axios = require('axios');
const jwt = require('jsonwebtoken');app.use(express.urlencoded({extended: true}));
app.use(express.json());
app.use(express.static("public"));
app.set('view engine', 'ejs');
然后我们添加路由。我们的应用会包含一个“get”路由和一个“post”路由。我们可以使用它们来获取输入数据,并将数据传递到 ONLYOFFICE 文档服务器的“post 请求”中:
app.get ('/', function (reg, response){
}app.post ('/converter', function(req, response){
}
客户端
现在我们花点时间,看看转换器的客户端。就是在这里,我们要输入所有所需数据:


客户端包括两个 EJS 页面:
- homepage.ejs:我们在这里提取“post 请求”所需的所有值。
- converter.ejs:我们在这里下载转换后的文件。
我们来详细看看“homepage.ejs”。这里我们创建了一个表单,将数据发送到“post”路由。首先,我们获得一个原始文件的URL。我们将把其存储在服务器端的“link”变量中:
<h1 class="h3 mb-3 font-weight-normal">Convert your OOXML files here!</h1><input type="text" class="form-control" id="inputEmail" placeholder="Paste a link to the file" name="link" onchange="activateBox()">
然后我们在组合框中选一个原始文件的类型。之后,我们提取这个值,并将其存储在“inputType”变量中:
<select class="form-control" id="inputType" input type="text" disabled="true" name="inputType" onchange="comboBox()"><option value="" selected>Input File Type</option><option value="docx">docx</option><option value="txt">txt</option><option value="pdf">pdf</option><option value="rtf">rtf</option><option value="xml">xml</option><option value="csv">csv</option><option value="xlsx">xlsx</option><option value="xls">xls</option><option value="ppt">ppt</option><option value="pptx">pptx</option>
</select>
然后,我们选择所需的文件类型。这个值会被储存在服务器端的“outputType”变量中:
<select class="form-control" id="outputType" input type="text" disabled="true" name="outputType" onchange="activateButton()"><option value="" disabled selected hidden>Output File Type</option></select>
我们用一个按钮将所有数据发送到“转换器”post 路由:
<div class="button"><button type="submit" id="download" disabled="true" class="btn btn-lg btn-primary btn-block">Convert</button></div></form>
构建转换器
提取的数据会在我们应用的服务器端进行解析。现在,我们前往“app.js”文件去获取:
app.post ('/converter', function(req, response){let link = req.body.link;let outputType = req.body.outputType;let fileType = req.body.inputType;});
现在我们看看第二个组合框,它将“outputType”值发送到“post”路由:
<select class="form-control" id="outputType" input type="text" disabled="true" name="outputType" onchange="activateButton()"><option value="" disabled selected hidden>Output File Type</option></select>
“outputType”变量包含在对服务器的“post 请求”中。它指定转换后的文件的格式。我们来看看支持我们与页面元素互动的 JavaScript 代码,并将动态列表并入我们的用户界面。
“文档转换服务”是一个非常强大的工具,能够转换各种类型的文件。所以我们的目标是利用一个动态列表,让我们为转换后的文件选择一种格式。这个列表会显示针对特定类型的原始文件的所有可用选项。
为此,我们创建一个 JSON 文件,按照每个特定的类型来存储数值:

请注意!在示范中,我们只列出了最常用的 OOXML 格式。如要了解所有受支持的转换选项,请访问我们的文档页面。
然后我们添加一个函数来生成这个动态列表:
function comboBox () {let type = document.querySelector("#inputType").value;let listDropDown = document.querySelector("#outputType");fetch("formats.json").then(function(response){return response.json();}).then(function(data){let options = data[type];let out = "";out += `<option value="">Output File Type</option>`;Object.values(options).map(function(format){out += '<option value=' + format + '>' + format + '</option>';});listDropDown.innerHTML = out;listDropDown.disabled = false;}); };};
首先,这个函数获取“inputType”组合框的值,我们在这里选择原始文件的格式。我们把它分配给“type”变量,以便在后面使用这个值。然后我们发出一个 AJAX 请求来加载 JSON 数据。之后,我们使用“type”变量的值作为索引,迭代加载的数据,将其值插入下拉列表的选项中。
现在,我们每次选择原始文件的类型时,脚本就会执行,并按照原始文件格式向我们显示可用的转换选项。
而在我们得到所有需要的数据后,点击“转换”按钮即可将其发送到转换器路由。
但实际不是这样。为了让我们的应用更具互动性,我们会添加函数,以正确的顺序激活组合框和按钮元素:
function activateBox() {$("#inputType").prop('disabled', false)};function activateButton() {$("#download").prop('disabled', false)$("#outputTypeForm").hide();};
完整的 JavaScript 代码如下:
function comboBox () {let type = document.querySelector("#inputType").value;let listDropDown = document.querySelector("#outputType");fetch("formats.json").then(function(response){return response.json();}).then(function(data){let options = data[type];let out = "";out += `<option value="">Output File Type</option>`;Object.values(options).map(function(format){out += '<option value=' + format + '>' + format + '</option>';});listDropDown.innerHTML = out;listDropDown.disabled = false;}); };function activateBox() {$("#inputType").prop('disabled', false)};function activateButton() {$("#download").prop('disabled', false)$("#outputTypeForm").hide();};}
我们来看看服务器端的状态:
app.post ('/converter', function(req, response){let link = req.body.link;let outputType = req.body.outputType;let fileType = req.body.inputType;let key = function () {var key = '';var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz0123456789';for (let i = 1; i <= 12; i++) {var char = Math.floor(Math.random()* str.length + 1);key += str.charAt(char);}return key;};const payload = { "async": true,"filetype": fileType,"key": key, "outputtype": outputType,"title": `Converted Document.${outputType}`,"url": link }let token = jwt.sign(payload, secret, options);axios.post( 'http://127.0.0.1:83/ConvertService.ashx',{ "token": token}) .then((res) => response.render('converter.ejs', {link: res.data.fileUrl}))
});
在“converter”路由中,我们生成了针对 ONLYOFFICE 文档服务器的 post 请求,并将其存储在“payload”变量中。我们使用了“fileType”、“outputType”和“link”变量,我们提取的数据也是存储在这些变量中。然而,我们还有一个“key”变量,包含当前文档的唯一标识符。所以我们在上面添加了一个小函数来将其生成:
let key = function () {var key = '';var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz0123456789';for (let i = 1; i <= 12; i++) {var char = Math.floor(Math.random()* str.length + 1);key += str.charAt(char)} return key;};
现在,所有关于请求的必要的值都齐备了,我们用 jwt.sign 把它们封装在一个令牌中:
let token = jwt.sign(payload, secret, options);
“jwt.sign”方法需要三个参数:
- Payload:包括成功转换所需的所有参数。
- Header:包含加密算法和过期时间范围相关信息。我们将这些参数封装在选项变量中。
- Secret:代表 ONLYOFFICE 文档服务器生成的密钥。您可以在 local.json 文件中找到这个密钥,或者通过在终端执行如下命令:
sudo docker exec <dockerID> /var/www/onlyoffice/documentserver/npm/json -f /etc/onlyoffice/documentserver/local.json 'services.CoAuthoring.secret.session.string'
在签署了令牌之后,我们再使用一个“axios post request”将其发送到服务器。然后我们呈现“converter.ejs”页面,该页面从 ONLYOFFICE 文档服务器接收响应:
axios.post( 'http://127.0.0.1:83/ConvertService.ashx',{ "token": token}) .then((res) => response.render('converter.ejs', {link: res.data.fileUrl}))
这是 JSON 格式响应的样本:
{ "endConvert": true, "fileType": "docx", "fileUrl": "https://documentserver/url-to-converted-document.pdf", "percent": 100 }
这里需要“fileUrl”元素,是指向转换后的文件的链接。所以我们要获取它,并将其发送到“converter.ejs”页面:
.then((res) => response.render('converter.ejs', {link: res.data.fileUrl}))
});
在该页面,我们创建两个按钮。“返回”按钮可让我们回到 homepage.ejs 页面;“下载”按钮则打开我们发送到该页面的链接,并下载转换后的文件:

请注意!如需详细了解 JWT,请访问我们的文档页面。
服务器端完整代码如下:
const express = require('express');
const app = express();
const axios = require('axios');
const jwt = require('jsonwebtoken');
const options = {algorithm: "HS256", expiresIn: "5m"};
const secret = "k1gWQdmDX6ZGiWw5r3g2";
app.use(express.urlencoded({extended: true}));
app.use(express.json());
app.use(express.static("public"));
app.set('view engine', 'ejs');
app.get ('/', function (reg, response){ response.render('homepage.ejs', {})
});
app.post ('/converter', function(req, response){let link = req.body.link;let outputType = req.body.outputType;let fileType = req.body.inputType;let key = function () {var key = '';var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz0123456789';for (let i = 1; i <= 12; i++) {var char = Math.floor(Math.random()* str.length + 1);key += str.charAt(char);}return key;};const payload = { "async": true,"filetype": fileType,"key": key, "outputtype": outputType,"title": `Converted Document.${outputType}`,"url": link }let token = jwt.sign(payload, secret, options);axios.post( 'http://127.0.0.1:83/ConvertService.ashx',{ "token": token}) .then((res) => response.render('converter.ejs', {link: res.data.fileUrl}))
});
app.listen(3000,() => console.log('the server is up and running'));
现在,我们来运行转换器,了解如何使用!

ONLYOFFICE 解决方案的功能非常丰富。这些解决方案为用户和开发者提供独特体验,让他们能够以多种方式操作 ooXML 文档。我们希望您觉得如上提到的信息很有用,并将其应用在您未来的项目中。欢迎您发表评论、提出问题或与我们分享您的想法,我们乐意接受建议、展开合作。祝您的探索一切顺利!
相关链接
ONLYOFFICE 文档服务器
转换 API 文档
签名文档
详细了解 JWT
相关文章:

使用 ONLYOFFICE 转换 API 构建在线文档转换器
文档转换是非常常用、非常有价值的功能,可以帮助我们处理多种文档类型。ONLYOFFICE 编辑器可以轻松地将文档转换为多种格式。在这篇博文中,我们会向您展示,如何构建在 ONLYOFFICE 转换 API 上运行的在线转换器。 关于 ONLYOFFICE 转换 API 使…...

Kubernetes的负载均衡方案:MetalLB
私有云裸金属架构(这是相对云上环境来说,不是说无操作系统)上部署的 Kubernetes 集群,通常是无法使用 LoadBalancer 类型的 Service 的。因为 Kubernetes 本身没有为裸机群集提供网络负载均衡器的实现。 如果你的 Kubernetes 集群没有在公有云的 IaaS 平台(GCP,AWS,Azu…...

【项目】Vue3+TS CMS 基本搭建相关配置
💭💭 ✨:Vue3 TS 💟:东非不开森的主页 💜: today beginning💜💜 🌸: 如有错误或不足之处,希望可以指正,非常感谢😉 基本…...

ros2 dds
问题1: fastdds发布的类型,ros2接收不到 原因: 在QoS相互兼容情况下,无法通信是由于idl类型没有使用兼容ros2的格式。如用 ros2 topic list -t 查看时,会发现同一个topic有两个不同的类型,如DDS会显示:myclass::peo…...

chain33架构介绍
chain33架构介绍 Chain33构架主要分为五个层级:数据层、网络层、共识层、激励层及应用层。 应用层:兼容以太坊智能合约,支持发行代币、资产交易、钱包找回,hash锁定等原生能力,同时支持用户可扩展执行器(…...

Lucene学习笔记
lucene结构 索引:概念上的一个表,现实体现就是一个文件目录,一个目录代表一个索引,也视作documents文档集合 文档:document,为索引中的一条数据,一个document可以拥有多个filed(域&a…...

动态规划【Day01】| 669 · 换硬币、114 · 不同的路径、116 · 跳跃游戏
秘诀:确定状态转移方程初始条件和边界情况计算顺序 669 换硬币 669 换硬币 题目描述: 给出不同面额的硬币以及一个总金额. 写一个方法来计算给出的总金额可以换取的最少的硬币数量. 如果已有硬币的任意组合均无法与总金额面额相等, 那么返回 -1。 样…...

1.Hello Python
Python Python 在网络爬虫、数据分析、AI、机器学习、Web开发、金融、运维、测试等多个领域都有不俗的表现,从来没有哪一种语言可以同时在这么多领域扎根。 Python基本语法 python关键字 关键字即保留字,和其他语言一样,这些关键字…...

C语言实例|编写C程序在控制台打印余弦曲线
C语言文章更新目录 C语言学习资源汇总,史上最全面总结,没有之一 C/C学习资源(百度云盘链接) 计算机二级资料(过级专用) C语言学习路线(从入门到实战) 编写C语言程序的7个步骤和编程…...

《Hadoop篇》------大数据及Hadoop入门
目录 一、大数据及Hadoop入门 1.1 单节点、分布式、集群 1.1.1 大数据的概念 1.1.2 大数据的本质 二、HDFS Shell命令 2.1、常用相关命令 2.2、上传文件 2.2.1、上传文件介绍 2.2.2上传文件操作 2.3、下载文件 2.4、删除文件 2.5、创建目录 2.6、查看文件系统 2.…...

TCP核心机制详解(三)
目录 前言: 滑动窗口 滑动窗口处理丢包问题 流量控制 拥塞控制 延时应答 捎带应答 面向字节流 异常情况 小结: 前言: 前两篇文章讲述了,TCP十种核心机制的前三种。这篇文章详细介绍其他的一些核心机制,让我们…...

最易上手的爬虫请求库:Requests核心功能速览(下)
上一个章节我们讲了如何快速使用Requests发送网络请求、处理URL参数和提取响应内容,这些是最基本的操作。 然而还有很多场景下,我们的网络请求更加复杂。比如我们必须要定制请求头来假装成浏览器,不然可能会被网站识别为机器并且被屏蔽;又比如我们需要在发送请求时以表单形…...

生产故障|Kafka ISR频繁伸缩引发性能急剧下降
生产故障|Kafka ISR频繁伸缩引发性能急剧下降-阿里云开发者社区 本文是笔者双十一系列第二弹,源于一个双十一期间一个让笔者猝不及防的生产故障,本文将详细剖析Kafka的副本机制,以及ISR频繁变更(扩张与伸缩)为什么会导致集群不可…...

c++终极螺旋丸:₍˄·͈༝·͈˄*₎◞ ̑̑“类与对象的结束“是结束也是开始
文章目录 前言一.构造函数中的初始化列表 拷贝对象时的一些编译器优化二.static成员三.友元四.内部类总结前言 前两期我们将类和对象的重点讲的差不多了,这一篇文章主要进行收尾工作将类和对象其他的知识点拉出来梳理一遍,并且补充前两篇没有讲过的…...

【Python--torch.nn.functional】F.normalize用法 + 代码说明
【Python–torch.nn.functional】F.normalize介绍 代码说明 文章目录【Python--torch.nn.functional】F.normalize介绍 代码说明1. 介绍2. 代码说明2.1 一维Tensor2.2 二维Tensor2.3 三维Tensor3. 总结1. 介绍 import torch.nn.functional as F F.normalize(input: Tensor, …...

【算法题】1887. 使数组元素相等的减少操作次数
插: 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 坚持不懈,越努力越幸运,大家一起学习鸭~~~ 题目: 给你一个整数数组 nums ࿰…...

GD库图片裁剪指定形状解决办法(PHP GD库 海报)
需求描述:需要把图片裁剪成一个指定的平行四边形,目的是使用GD库,把裁剪后的图片放在底图上面,使最终合成的图片看起来是一个底图平行四边形的样子提示:可以结合本作者的其他文章,来生成一个定制化的海报&a…...

redis的简介及应用场景
1、基本信息 Redis英文官网介绍: Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queri…...

2、HAL库利用滴答定时器systick(1ms中断)实现时间计数戳
文档说明:通过滴答定时器的1ms中断实现时间计数,标记需要的时间标志,在主函数中查询标志,避免延时函数消耗CPU 1、HAL库systick定时器说明 在CubeMx生成的代码main()函数首先执行的函数为HAL_Init();里面会进行滴答定时器初始化…...

Spring入门学习
Spring入门学习 文章目录Spring入门学习Spring概述Spring FrameworkIOCIOC容器DIIOC容器的实现类①FileSystemXmlApplicationContext②ClassPathXmlApplicationContext基于XML管理bean入门案例创建类创建xml在Spring配置文件中配置bean测试Spring概述 Spring 是最受欢迎的企业级…...

webpack(4版本)使用
webpack简介:webpack 是一种前端资源构建工具,一个静态模块打包器(module bundler)。在 webpack 看来, 前端的所有资源文件(js/json/css/img/less/...)都会作为模块处理。它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)…...

Linux安装ElasticSearch
下载地址:https://www.elastic.co/cn/downloads/past-releases#elasticsearch 1 版本选择 ElasticSearch 7 及以上版本都是自带的 jdk,假如需要配置指定的 jdk 版本的话,可以在 es 的 bin 目录下找到elasticsearch-env.bat 这个文件&#x…...

Linux中C语言编程经验总结
修改记录 版本号日期更改理由V1.02022-03-15MD化 总则 仅总结一些常用且实用的编程规范和技巧,且避免记忆负担,聚焦影响比较大的20% ! 编译器 打开全warning编译器开关 正例 gcc -W -Wall -g -o someProc main.c反例 gcc -g -o someProc main…...

jvisualvm工具使用
jdk自带的工具jvisualvm,可以分析java内存使用情况,jvm相关的信息。 1、设置jvm启动参数 设置jvm参数**-Xms20m -Xmx20m -XX:PrintGCDetails** 最小和最大堆内存,打印gc详情 2、测试代码 TestScheduleClassGc package com.core.schedule;…...

redis五大IO网络模型、内存回收
目录1.0用户空间和内核态空间1.1 网络模型-阻塞IO1.2 网络模型-非阻塞IO1.3 网络模型-IO多路复用1.3.1 网络模型-IO多路复用-select方式1.3.2 网络模型-IO多路复用模型-poll模式1.3.3 网络模型-IO多路复用模型-epoll函数1.3.4 网络模型-epoll中的ET和LT1.3.5 网络模型-基于epol…...

【C/C++】内存管理详解
目录内存布局思维导图1.C/C内存分布数据段:栈:代码段:堆:2.C语言中动态内存管理方式3.C内存管理方式3.1new/delete操作内置类型3.2new和delete操作自定义类型4.operator new 与 operator delete函数5.new和delete的实现原理5.1内置类型5.2自定…...

Android ProcessLifecycleOwner 观察进程生命周期
文章目录简介使用依赖用法1,结合 LiveData用法2,获取 owner的 lifecycle 实例,并对 lifecycle 添加观察者简介 ProcessLifecycleOwner 直译,就是,进程生命周期所有者。 通过 DOC 注释了解到: Lifecycle.E…...

如何编写一个 npm 插件?
提到写 npm 插件,很多没搞过的可能第一感觉觉得很难,无从下手,其实不然。 我们甚至写个简单的 console.log(hello word),都是可以当成一个插件发布上去的。 其实无从下手的主要难点还是在于你的具体要做的功能逻辑,这…...

mapstruct- 让VO,DTO,ENTITY转换更加便捷
mapstruct- 让VO,DTO,ENTITY转换更加便捷 1. 简介 MapStruct是一个代码生成器,简化了不同的Java Bean之间映射的处理,所谓映射指的就是从一个实体变化成一个实体。例如我们在实际开发中,DAO层的实体和一些数据传输对…...

IAR警告抑制及还原
工作中需要临时抑制 警告 Pa084,源代码如下: sy_errno_t sy_memset_s(void *dest, sy_rsize_t dmax, int value, sy_rsize_t n) { sy_errno_t err; if (dest NULL) { return SY_ESNULLP; } if (dmax > SY_RSIZE…...