文檔轉(zhuǎn)換是非常常用、非常有價(jià)值的功能,可以幫助我們處理多種文檔類型。ONLYOFFICE 編輯器可以輕松地將文檔轉(zhuǎn)換為多種格式。在這篇博文中,我們會向您展示,如何構(gòu)建在 ONLYOFFICE 轉(zhuǎn)換 API 上運(yùn)行的在線轉(zhuǎn)換器。

關(guān)于 ONLYOFFICE 轉(zhuǎn)換 API
使用文檔轉(zhuǎn)換服務(wù),您可就各種類型的 Office 文檔做轉(zhuǎn)換:文本、表格、幻燈片、表單、PDF 和電子書。它幫助您基于文檔和表格創(chuàng)建 PDF,將教科書轉(zhuǎn)換為電子書,將演示文稿轉(zhuǎn)換為圖片文件,等等。ONLYOFFICE 支持 50 多種文件類型。
操作方法
我們的轉(zhuǎn)換 API 通過“文檔轉(zhuǎn)換服務(wù)”運(yùn)行。它是 ONLYOFFICE 文檔服務(wù)器的一部分,支持我們將各種文檔文件轉(zhuǎn)換為合適的格式。
轉(zhuǎn)換要分幾個(gè)步驟進(jìn)行:
- 用戶選擇一個(gè)要上傳到“文檔管理器”的文件。
- “文檔管理器”將選定的文件上傳到“文檔存儲服務(wù)”。
- “文檔存儲服務(wù)”通過使用“轉(zhuǎn)化 API”將上傳的文件發(fā)送到“文檔轉(zhuǎn)換服務(wù)”。
- “文檔轉(zhuǎn)換服務(wù)”將選定的文件轉(zhuǎn)換為目標(biāo)格式。
- “文檔存儲服務(wù)”下載轉(zhuǎn)換后的文檔文件。

“文檔管理器”和“文檔存儲服務(wù)”是客戶端和服務(wù)器端的工具,方便選擇和存儲文檔供進(jìn)一步轉(zhuǎn)換。不過,我們的 web 應(yīng)用會處理這些任務(wù),這得益于我們正在構(gòu)建的自定義轉(zhuǎn)換器。
前提條件
我們的轉(zhuǎn)換器基于 NodeJS。因此,對于這個(gè)項(xiàng)目,我們需要如下條件:
- ONLYOFFICE 文檔服務(wù)器
- 安裝了如下軟件包的 NodeJS 應(yīng)用:
– Express
– Axios
– Jsonwebtoken
我們會使用 Axios 包向 ONLYOFFICE 文檔服務(wù)器發(fā)送一個(gè) post 請求,并使用 Jsonwebtoken 包簽署一個(gè) JWT 令牌。從版本 7.2 開始,JWT 認(rèn)證默認(rèn)處于啟用狀態(tài)。
或者,您還可以通過另一個(gè)選項(xiàng),在 JWT 認(rèn)證停用的情況下運(yùn)行 ONLYOFFICE 文檔服務(wù)器鏡像。為此,請?jiān)诮K端執(zhí)行如下命令:
sudo docker run -i -t -d -p 80:80 -e JWT_ENABLED=false onlyoffice/documentserver
我們的轉(zhuǎn)換器向 ONLYOFFICE 文檔服務(wù)器發(fā)送的“post 請求”如下:
{
"async": true,
"filetype": fileType,
"key": key,
"outputtype": outputType,
"title": `Converted Document.${outputType}`,
"url": link
}
- 在“accept”參數(shù)中,我們指定要接收 JSON 格式的響應(yīng)。
- “async”參數(shù)指示該請求是異步請求。
- “fileType”參數(shù)指定我們要轉(zhuǎn)換的原始文件的類型。
- “key”參數(shù)指定當(dāng)前文件的唯一標(biāo)識符 (UID)。
- “outputType”參數(shù)指定轉(zhuǎn)換后的文件的格式。
- “title”參數(shù)包含轉(zhuǎn)換后的文檔的名稱。
- “url”參數(shù)包含指向我們要轉(zhuǎn)換的文件的鏈接。
“fileType”、“outputType”和“url”參數(shù)的值是從我們應(yīng)用的客戶端獲取,存儲在變量中?!発ey”參數(shù)的值也是隨機(jī)生成,存儲在變量中。
項(xiàng)目設(shè)置
將所需的包安裝好后,我們前往“app.js”文件,將它們與“bodyParser”一起初始化,以處理“post 請求”數(shù)據(jù)。我們還創(chuàng)建了一個(gè)公開文件夾和一個(gè)視圖引擎:
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');
然后我們添加路由。我們的應(yīng)用會包含一個(gè)“get”路由和一個(gè)“post”路由。我們可以使用它們來獲取輸入數(shù)據(jù),并將數(shù)據(jù)傳遞到 ONLYOFFICE 文檔服務(wù)器的“post 請求”中:
app.get ('/', function (reg, response){
}
app.post ('/converter', function(req, response){
}
客戶端
現(xiàn)在我們花點(diǎn)時(shí)間,看看轉(zhuǎn)換器的客戶端。就是在這里,我們要輸入所有所需數(shù)據(jù):


客戶端包括兩個(gè) EJS 頁面:
- homepage.ejs:我們在這里提取“post 請求”所需的所有值。
- converter.ejs:我們在這里下載轉(zhuǎn)換后的文件。
我們來詳細(xì)看看“homepage.ejs”。這里我們創(chuàng)建了一個(gè)表單,將數(shù)據(jù)發(fā)送到“post”路由。首先,我們獲得一個(gè)原始文件的URL。我們將把其存儲在服務(wù)器端的“l(fā)ink”變量中:
<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()">
然后我們在組合框中選一個(gè)原始文件的類型。之后,我們提取這個(gè)值,并將其存儲在“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>
然后,我們選擇所需的文件類型。這個(gè)值會被儲存在服務(wù)器端的“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>
我們用一個(gè)按鈕將所有數(shù)據(jù)發(fā)送到“轉(zhuǎn)換器”post 路由:
<div class="button">
<button type="submit" id="download" disabled="true" class="btn btn-lg btn-primary btn-block">Convert</button>
</div>
</form>
構(gòu)建轉(zhuǎn)換器
提取的數(shù)據(jù)會在我們應(yīng)用的服務(wù)器端進(jìn)行解析?,F(xiàn)在,我們前往“app.js”文件去獲?。?/p>
app.post ('/converter', function(req, response){
let link = req.body.link;
let outputType = req.body.outputType;
let fileType = req.body.inputType;
});
現(xiàn)在我們看看第二個(gè)組合框,它將“outputType”值發(fā)送到“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”變量包含在對服務(wù)器的“post 請求”中。它指定轉(zhuǎn)換后的文件的格式。我們來看看支持我們與頁面元素互動的 JavaScript 代碼,并將動態(tài)列表并入我們的用戶界面。
“文檔轉(zhuǎn)換服務(wù)”是一個(gè)非常強(qiáng)大的工具,能夠轉(zhuǎn)換各種類型的文件。所以我們的目標(biāo)是利用一個(gè)動態(tài)列表,讓我們?yōu)檗D(zhuǎn)換后的文件選擇一種格式。這個(gè)列表會顯示針對特定類型的原始文件的所有可用選項(xiàng)。
為此,我們創(chuàng)建一個(gè) JSON 文件,按照每個(gè)特定的類型來存儲數(shù)值:

請注意!在示范中,我們只列出了最常用的 OOXML 格式。如要了解所有受支持的轉(zhuǎn)換選項(xiàng),請?jiān)L問我們的文檔頁面。
然后我們添加一個(gè)函數(shù)來生成這個(gè)動態(tài)列表:
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;
});
};
};
首先,這個(gè)函數(shù)獲取“inputType”組合框的值,我們在這里選擇原始文件的格式。我們把它分配給“type”變量,以便在后面使用這個(gè)值。然后我們發(fā)出一個(gè) AJAX 請求來加載 JSON 數(shù)據(jù)。之后,我們使用“type”變量的值作為索引,迭代加載的數(shù)據(jù),將其值插入下拉列表的選項(xiàng)中。
現(xiàn)在,我們每次選擇原始文件的類型時(shí),腳本就會執(zhí)行,并按照原始文件格式向我們顯示可用的轉(zhuǎn)換選項(xiàng)。
而在我們得到所有需要的數(shù)據(jù)后,點(diǎn)擊“轉(zhuǎn)換”按鈕即可將其發(fā)送到轉(zhuǎn)換器路由。
但實(shí)際不是這樣。為了讓我們的應(yīng)用更具互動性,我們會添加函數(shù),以正確的順序激活組合框和按鈕元素:
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();
};
}
我們來看看服務(wù)器端的狀態(tài):
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 文檔服務(wù)器的 post 請求,并將其存儲在“payload”變量中。我們使用了“fileType”、“outputType”和“l(fā)ink”變量,我們提取的數(shù)據(jù)也是存儲在這些變量中。然而,我們還有一個(gè)“key”變量,包含當(dāng)前文檔的唯一標(biāo)識符。所以我們在上面添加了一個(gè)小函數(shù)來將其生成:
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;
};
現(xiàn)在,所有關(guān)于請求的必要的值都齊備了,我們用 jwt.sign 把它們封裝在一個(gè)令牌中:
let token = jwt.sign(payload, secret, options);
“jwt.sign”方法需要三個(gè)參數(shù):
- Payload:包括成功轉(zhuǎn)換所需的所有參數(shù)。
- Header:包含加密算法和過期時(shí)間范圍相關(guān)信息。我們將這些參數(shù)封裝在選項(xiàng)變量中。
- Secret:代表 ONLYOFFICE 文檔服務(wù)器生成的密鑰。您可以在 local.json 文件中找到這個(gè)密鑰,或者通過在終端執(zhí)行如下命令:
sudo docker exec <dockerID> /var/www/onlyoffice/documentserver/npm/json -f /etc/onlyoffice/documentserver/local.json 'services.CoAuthoring.secret.session.string'
在簽署了令牌之后,我們再使用一個(gè)“axios post request”將其發(fā)送到服務(wù)器。然后我們呈現(xiàn)“converter.ejs”頁面,該頁面從 ONLYOFFICE 文檔服務(wù)器接收響應(yīng):
axios.post(
'http://127.0.0.1:83/ConvertService.ashx',
{
"token": token
})
.then((res) => response.render('converter.ejs', {
link: res.data.fileUrl
}))
這是 JSON 格式響應(yīng)的樣本:
{ "endConvert": true, "fileType": "docx", "fileUrl": "https://documentserver/url-to-converted-document.pdf", "percent": 100 }
這里需要“fileUrl”元素,是指向轉(zhuǎn)換后的文件的鏈接。所以我們要獲取它,并將其發(fā)送到“converter.ejs”頁面:
.then((res) => response.render('converter.ejs', {
link: res.data.fileUrl
}))
});
在該頁面,我們創(chuàng)建兩個(gè)按鈕?!胺祷亍卑粹o可讓我們回到 homepage.ejs 頁面;“下載”按鈕則打開我們發(fā)送到該頁面的鏈接,并下載轉(zhuǎn)換后的文件:

請注意!如需詳細(xì)了解 JWT,請?jiān)L問我們的文檔頁面。
服務(wù)器端完整代碼如下:
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'));
現(xiàn)在,我們來運(yùn)行轉(zhuǎn)換器,了解如何使用!

ONLYOFFICE 解決方案的功能非常豐富。這些解決方案為用戶和開發(fā)者提供獨(dú)特體驗(yàn),讓他們能夠以多種方式操作 ooXML 文檔。我們希望您覺得如上提到的信息很有用,并將其應(yīng)用在您未來的項(xiàng)目中。歡迎您發(fā)表評論、提出問題或與我們分享您的想法,我們樂意接受建議、展開合作。祝您的探索一切順利!