Для конвертации документов требуется выполнить запрос к серверу.
Запрос состоит из нескольких важных участков:
- формирование JSON запроса
- формирование token на основе созданного запроса
Далее обработка получения ответа
JSON – может быть следующего вида:
{ "async": false, "filetype":"docx", "key":"unique identifier", "outputtype":"pdfa", "url":"https://path_to_url.ru/example..docx" }
где async — Определяет тип запроса на преобразование: асинхронный или нет.
Поддерживаемые ценности:
- true
- false
Когда используется асинхронный тип запроса, ответ формируется мгновенно. В этом случае для получения результата необходимо отправлять запросы без изменения параметра до завершения преобразования. Значение по умолчанию — false.
- filetype – расширение передаваемого на сервер документа,
- key – уникальный ключ, который идентифицирует документ на сервере,
- outputtype – тип выходного файла,
- url – передаваемый файл для конвертации.
Token формируется из 3-х частей и передается вместе с запросом.
1) Первая часть, это
header = { "alg": "HS256", "typ": "JWT" }
2) Вторая часть, это
payload = { "async":false, "filetype":"docx", "key": "td6gdi2ilfqk", "outputtype":"pdfa", "url": "https://path_to_url.ru/example..docx" };
3) Третья часть, это сам secret сервера документов.
Далее необходимо закодировать каждую часть в Base64 и объединить все вместе. На сайте https://jwt.io можно получить токен используя header, payload и secret.
Пример рабочего Token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhc3luYyI6ZmFsc2UsImZpbGV0eXBlIjoiZG9jeCIsImtleSI6InRkNmdkaTJpbGZxayIsIm91dHB1dHR5cGUiOiJwZGZhIiwidXJsIjoiaHR0cHM6Ly9wYXRoX3RvX3VybC5ydS9leGFtcGxlLi5kb2N4In0.RdYuJfvelAqpVUMxAYGfknxE7dUCUJgUXFhegm_Amms
Вы можете заметить, что каждая часть отделена точкой.
Для проверки вы можете воспользоваться сервисом https://jwt.io
Так же в header самого запроса необходимо добавить:
- Accept application/json
Сам запрос отправляется с методом POST по адресу http://Имя_сервера_документов/ConvertService.ashx
Или если сервер документов в составе корпоративного сервера, тогда адрес
http://Имя_сервера_документов/ds-vpath/ConvertService.ashx
Ниже пример передачи запроса по средствам JS:
const xhr = new XMLHttpRequest(); xhr.open("POST", "http://Имя_сервера_документов/ds-vpath/ConvertService.ashx", true); xhr.setRequestHeader("Accept ", " application/json "); xhr.onreadystatechange = () => { // Вызов функции когда придет ответ от сервера if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) { // Ответ обрабатывается здесь. // Например вывод в консоль let responseObj = this.responseText; // необходимо из ответа получить JSON var json = JSON.parse(xhr.responseText); let fileUrl = json.fileUrl; console.log(“URL: “ + fileUrl); } }; xhr.send(JSON.stringify({ "token": token}));
Донастройка сервера
Для того чтобы сервер документов не отбрасывал внешний запрос как CORS необходимо дать разрешение на внешние запросы. Пример как это организовать на стороне nginx в файле конфигурации:
add_header Access-Control-Allow-Origin * always; add_header Access-Control-Allow-Headers * always;
docker ps
Получаете id контейнера.
docker exec id_контейнера /bin/bash nano /etc/nginx/nginx.conf
Вставить записи
add_header Access-Control-Allow-Origin * always; add_header Access-Control-Allow-Headers * always;
Пример
http { ## # Basic Settings ## add_header Access-Control-Allow-Origin * always; add_header Access-Control-Allow-Headers * always; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # server_tokens off;
4. Сохранить файл, выполнить скрипт командой
documentserver-prepare4shutdown.sh
и выйти из контейнера командой
exit
5. Перезагрузить контейнер командой:
docker restart id_контейнера
Вместо * можно указать адреса хостов с которых разрешены внешние запросы.
В ответ на запрос придет ответ вида:
{ "fileUrl": "http://Имя_сервера_документов/ds-vpath/cache/files/data/conv_k2547nwpotob_pdfa/output.pdf/output.pdf?md5=2VxPLKpfQpbUu5t8L3EDNQ&expires=1705243012&filename=output.pdf", "fileType": "pdf", "percent": 100, "endConvert": true }
На сервере отключен JWT
Для этого Вам необходимо:
Открыть на стороне Р7-Офис Сервер файл /etc/r7-office/documentserver/local.json
и измените значения inbox, outbox, browser на false, как указано на примере:
"inbox": false, "outbox": false }, "browser": false }, "inbox": { "header": "Authorization" }, "outbox": { "header": "Authorization"
Из первой части потребуется сформировать только payload
payload = { "async":false, "filetype":"docx", "key": "td6gdi2ilfqk", "outputtype":"pdfa", "url": "https://path_to_url.ru/example..docx" };
Ниже пример передачи запроса по средствам JS без Token:
const xhr = new XMLHttpRequest(); xhr.open("POST", "http://Имя_сервера_документов/ds-vpath/ConvertService.ashx", true); xhr.setRequestHeader("Accept ", " application/json "); xhr.onreadystatechange = () => { // Вызов функции когда придет ответ от сервера if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) { // Ответ обрабатывается здесь. // Например вывод в консоль let responseObj = this.responseText; // необходимо из ответа получить JSON var json = JSON.parse(xhr.responseText); let fileUrl = json.fileUrl; console.log(“URL: “ + fileUrl); } }; xhr.send(JSON.stringify(payload));
Ниже пример HTML страницы презентации примера работы
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> Отправляем JSON-данные на сервер </title> <style> .lds-ring { display: inline-block; position: relative; width: 80px; height: 80px; } .lds-ring div { box-sizing: border-box; display: block; position: absolute; width: 64px; height: 64px; margin: 8px; border: 8px solid #fff; border-radius: 50%; animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite; border-color: #07f transparent transparent transparent; } .lds-ring div:nth-child(1) { animation-delay: -0.45s; } .lds-ring div:nth-child(2) { animation-delay: -0.3s; } .lds-ring div:nth-child(3) { animation-delay: -0.15s; } @keyframes lds-ring { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } </style> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> </head> <body style="text-align:center;" id="body"> <script> // ниже функция вызова анимации крутилки function setCircle() { var result = document.querySelector('.result'); result.innerHTML = ` <div class="lds-ring"><div></div><div></div><div></div><div></div> </div>` } // ниже функция конвертации function convert() { setCircle(); // вызов анимации загрузки var result = document.querySelector('.result'); // получить элемент с классом result let address = document.getElementById('address').value; // получить значение из элемента с ID address let path = document.getElementById('path').value; // получить значение из элемента с ID path // создаём новый экземпляр запроса XHR let xhr = new XMLHttpRequest(); // адрес, куда мы отправим наш запрос на конвертацию let url = address+"/ds-vpath/ConvertService.ashx"; // открываем соединение xhr.open("POST", url, true); // устанавливаем заголовоки, которые отправятся на сервер //xhr.setRequestHeader("Accept", "application/json"); //xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.setRequestHeader('Access-Control-Allow-Headers', '*'); //xhr.setRequestHeader('Content-type', 'application/ecmascript'); xhr.setRequestHeader('Access-Control-Allow-Origin', '*'); //«Access-Control-Allow-Origin» //xhr.setRequestHeader("Content-Type", "application/json"); xhr.setRequestHeader("Accept", "application/json"); xhr.setRequestHeader("Access-Control-Allow-Methods", "*"); // таймаут в миллисекундах xhr.timeout = 10000; // по истечении таймаута отработает функция сброса запроса и выведет сообщение xhr.ontimeout = (e) => { result.innerHTML = "<p>Время вышло. Повторите еще раз...</p>"; }; // когда придёт ответ на наше обращение к серверу, мы его обработаем здесь xhr.onreadystatechange = function () { // если запрос принят и сервер ответил, что всё в порядке if (xhr.readyState === 4 && (xhr.status >= 200 && xhr.status <= 300)) { // выводим то, что ответил нам сервер — так мы убедимся, что данные он получил правильно let responseObj = this.responseText; // необходимо из ответа получить JSON var json = JSON.parse(xhr.responseText); if (json.error) { switch (json.error) { case -1: result.innerHTML = "<p>Unknown error.</p>"; break; case -2: result.innerHTML = "<p>Conversion timeout error.</p>"; break; case -3: result.innerHTML = "<p>Conversion error.</p>"; break; case -4: result.innerHTML = "<p>Error while downloading the document file to be converted.</p>"; break; case -5: result.innerHTML = "<p>Incorrect password</p>"; break; case -6: result.innerHTML = "<p>Error while accessing the conversion result database.</p>"; break; case -7: result.innerHTML = "<p>Input error.</p>"; break; case -8: result.innerHTML = "<p>Invalid token.</p>"; break; case -9: result.innerHTML = `<p>Error when the converter cannot automatically determine the output file format. This error means that the client must explicitly specify in which format the file should be converted (text document or spreadsheet). It is used to convert XML to OOXML in case the XML type is unknown.</p>`; break; default: result.innerHTML = "<p>Неизвестная ошибка</p>"; } } else { // получаем из ответа URL и присваиваем в переменную let fileUrl = json.fileUrl; // Формируем ответ на странице result.innerHTML = "<a href="+fileUrl+">Скачать файл</a>"; } } // если запрос отработал с ошибкой if (xhr.status == 0) { // выводим сообщение об ошибке result.innerHTML = "error"; } if (xhr.status >= 301) { // выводим то, что ответил нам сервер — так мы убедимся, что данные он получил правильно var json = JSON.parse(xhr.responseText); result.innerHTML = json.error.message; //console.log(json); } }; let newkey = Math.random().toString(36).slice(-6) + Math.random().toString(36).slice(-6); let payload = { "async":false, "filetype":"docx", "key": newkey, "title": null, "outputtype":"pdfa", "url": path }; var data = JSON.stringify(payload); // когда всё готово, отправляем запрос на сервер xhr.send(data); } </script> <!-- заголовок --> <h1> Простая форма для конвертации docx в pdf </h1> <!-- делаем форму с полями ввода --> <span style="display: flex; justify-content: center;"> <table> <tr> <td> <label for="address">address with http(s)//: </label> <p><input type="text" id="address" name="address" value="http://URL_TO_YOUR_CS_SERVER"></p> </td> <td> <label for="path">path to file: </label> <p><input type="text" id="path" name="path" value="https://freetestdata.com/wp-content/uploads/2021/09/Free_Test_Data_1MB_DOCX-1.docx"></p> </td> </tr> </table> </span> <p> <!-- по нажатию на эту кнопку данные уйдут на сервер --> <button onclick="convert()">Сконвертировать</button> <!-- а вот тут они появятся снова, но уже после обработки сервером --> <div class="result" style="color:blue"> </div> </p> </body> </html>