SFTP ve výpočtech v TAS 5.7
Návod pro konzultanty, kteří potřebují z výpočtu na úkolu v TAS 5.7 odeslat soubor na SFTP server nebo ho odtud stáhnout. Verze 5.7 nemá samostatné ftp API, přenos souborů se dělá přes objekt curl (knihovna node-libcurl). Objekt axios umí jen HTTP a HTTPS. Postup je ověřený na instanci TAS 5.7.105: čtení proti SFTP serveru (výpis, stažení textového i binárního souboru, chybové stavy, heslo ze secretu), zápis (upload, přejmenování, vytvoření a smazání adresáře, stažení zpět) proti FTP serveru podle kapitoly 9. Mechanismus uploadu a QUOTE příkazů je u obou protokolů stejný, liší se jen názvy příkazů.
curl v 5.7 umí SFTP (SSH, port 22). Pro klasické FTP (port 21) je potřeba ve výpočtu navíc nastavit volbu PROTOCOLS_STR, jinak curl.perform() skončí chybou Unsupported protocol. Postup je v kapitole 9.Co 5.7 umí a neumí
Potřeba |
TAS 5.7 |
Jak |
HTTP/HTTPS REST volání |
ano |
|
SFTP – upload, download, výpis, mazání |
ano |
|
Klasické FTP (port 21) |
ano |
|
Samostatné |
ne |
od verze 5.12.22, viz FTP a SFTP použití ve výpočtech |
SmartEvent „FTP requester" |
ne |
až v novějších verzích |
Chování objektu curl v 5.7
- Objekt
curlje k dispozici jen ve výpočtech úlohy (Task JS) a v identity výpočtech. Ve výpočtu na případu ani v konzoli výpočtů není. - Výchozí protokoly jsou HTTP, HTTPS a SFTP. FTP se zapíná volbou
PROTOCOLS_STR(kapitola 9). - Po prvním
curl.perform()se do logu backendu zapíše varování, žeCurlApije zastaralé. Je to jen varování, funkce běží normálně. - Kontrola šablony před upgradem (
system.validateTemplate(tprocId)) hlásí každé použitícurl.*textem „removed, use FtpApi". V 5.7 to ignorujte, je to příprava na upgrade. curl.perform()po dokončení spojení zavře. Pro další požadavek ve stejném výpočtu zavolejte znovucurl.start(), jinak skončí chybouCurl handle is closed.- Výsledek
perform()je objekt{ statusCode, data, headers }. U SFTP jestatusCodevždy0, chyby přicházejí jako výjimka. - Výchozí timeout je 60 s. U větších souborů nastavte
curl.setOpt('TIMEOUT', 600).
1. Ověření, že server má SFTP v libcurl
Spusťte v testovacím výpočtu na úloze (v konzoli výpočtů objekt curl není):
vars['vysledek'].setValue(curl.info());
Ve výstupu musí být sftp v seznamu protokolů a libssh2 (nebo libssh) mezi knihovnami. Standardní image 5.7 má libcurl/7.86.0 … libssh2/1.10.0 a v protokolech scp, sftp. Pokud chybí, je image bez SSH podpory a je nutné to řešit na úrovni instalace.
2. Přihlašovací údaje
Tři možnosti, od nejjednodušší po nejbezpečnější.
a) V URL
Vhodné jen pro test, heslo je v textu šablony.
curl.setOpt('URL', 'sftp://uzivatel:heslo@sftp.example.com:22/export/soubor.txt');
Speciální znaky v hesle musí být URL-encodované (@ → %40, : → %3A, / → %2F). Jednodušší je použít encodeURIComponent(heslo).
b) Volbou USERPWD
URL je pak bez přihlašovacích údajů a odpadá encodování.
curl.setOpt('URL', 'sftp://sftp.example.com:22/export/soubor.txt');
curl.setOpt('USERPWD', 'uzivatel:heslo');
c) Z tajemství (secret)
Heslo není v kódu šablony. Secret se jmenuje libovolně a jeho hodnota je řetězec uzivatel:heslo. Nastaví se buď v local.js v klíči secrets, nebo jednorázově výpočtem (hodnota se uloží do konfigurace instance, výpočet pak ze šablony odstraňte):
await lib.setSecret('sftpExport', 'uzivatel:heslo');
Ve výpočtu se pak místo curl.perform() volá curl.performSecureAuth(nazevSecretu), které secret načte, nastaví USERPWD a požadavek provede:
curl.setOpt('URL', 'sftp://sftp.example.com:22/export/soubor.txt');
const response = await curl.performSecureAuth('sftpExport');
USERPWD vidí každý, kdo smí editovat šablonu.Klíč místo hesla
libcurl podporuje volby SSH_PRIVATE_KEYFILE a SSH_PUBLIC_KEYFILE (cesta k souboru na serveru TAS, typicky v mapovaném svazku). Tato varianta není pokrytá testy platformy, funguje na úrovni libcurl.
3. Stažení souboru ze SFTP
Textový soubor, odpověď přijde jako string:
curl.start();
curl.setOpt('URL', 'sftp://sftp.example.com:22/export/data.csv');
curl.setOpt('USERPWD', 'uzivatel:heslo');
curl.setOpt('TIMEOUT', 300);
const { data } = await curl.perform();
vars['csvObsah'].setValue(data);
Binární soubor (PDF, XLSX, ZIP) a uložení do DMS případu. Bez curl.enable('Raw') se obsah poškodí převodem na string (ověřeno: PNG o velikosti 19 156 B dorazil jako řetězec 18 136 znaků):
curl.start();
curl.setOpt('URL', 'sftp://sftp.example.com:22/export/faktura.pdf');
curl.setOpt('USERPWD', 'uzivatel:heslo');
curl.setOpt('TIMEOUT', 300);
curl.enable('Raw');
const { data } = await curl.perform(); // data je Buffer
const dmsfId = await lib.storeAttachment('faktura.pdf', data);
lib.storeAttachment(nazev, Buffer) uloží soubor jako přílohu aktuálního případu a vrátí jeho DMS ID. Pokud ho chcete přiřadit do proměnné typu příloha, nastavte jí vrácené ID.
4. Nahrání souboru na SFTP
Obsah vytvořený ve výpočtu, například CSV:
const csv = 'id;nazev\n1;Test\n';
const datum = new Date().toISOString().slice(0, 10); // 2026-11-09
curl.start();
curl.setOpt('URL', 'sftp://sftp.example.com:22/import/export_' + datum + '.csv');
curl.setOpt('USERPWD', 'uzivatel:heslo');
curl.setOpt('TIMEOUT', 300);
curl.setOpt('UPLOAD', true);
curl.sendBinaryBuffer(Buffer.from(csv, 'utf-8'));
await curl.perform();
Příloha z DMS (proměnná typu příloha, název souboru nebo DMS ID):
const obsah = await storage.getDmsContent(vars['priloha'], 'buffer'); // Buffer
curl.start();
curl.setOpt('URL', 'sftp://sftp.example.com:22/import/' + encodeURIComponent('smlouva.pdf'));
curl.setOpt('USERPWD', 'uzivatel:heslo');
curl.setOpt('TIMEOUT', 600);
curl.setOpt('UPLOAD', true);
curl.sendBinaryBuffer(obsah);
await curl.perform();
UPLOAD a sendBinaryBuffer před perform. Cílový adresář musí na serveru existovat, SFTP ho při uploadu nevytvoří (viz kapitola 6). Bez práva zápisu skončí perform() chybou Access denied to remote resource. Upload přes UPLOAD + sendBinaryBuffer a stažení zpět byly ověřeny proti FTP serveru (35 B včetně diakritiky, obsah shodný).5. Výpis adresáře
URL musí končit lomítkem. Výchozí výstup je dlouhý formát jako ls -l; volba DIRLISTONLY vrátí jen názvy, jeden na řádek:
curl.start();
curl.setOpt('URL', 'sftp://sftp.example.com:22/export/');
curl.setOpt('USERPWD', 'uzivatel:heslo');
curl.setOpt('DIRLISTONLY', true);
const { data } = await curl.perform();
const soubory = data.split('\n').filter(n => n && n !== '.' && n !== '..');
return soubory;
Bez DIRLISTONLY přijde výpis ve tvaru -rw------- 1 demo users 379 Sep 19 2023 readme.txt, jeden záznam na řádek, včetně . a ...
6. Mazání, přejmenování, vytvoření adresáře
libcurl umí na SFTP spustit příkazy přes volbu QUOTE (před přenosem) nebo POSTQUOTE (po přenosu). Podporované příkazy: rm, rmdir, rename, mkdir, chmod, ln, symlink. Příkazy se posílají hned po přihlášení, ještě před přechodem do adresáře z URL, proto v nich uvádějte absolutní cesty; relativní cesta se vyhodnotí vůči kořeni účtu. Pokud příkaz na serveru selže (chybějící práva, neexistující cesta), perform() vyhodí Quote command returned error.
Smazání souboru po úspěšném stažení (vzor „zpracuj a ukliď"):
curl.start();
curl.setOpt('URL', 'sftp://sftp.example.com:22/export/data.csv');
curl.setOpt('USERPWD', 'uzivatel:heslo');
curl.setOpt('POSTQUOTE', ['rm /export/data.csv']);
const { data } = await curl.perform();
Přesun do archivu po nahrání:
curl.setOpt('POSTQUOTE', ['rename /import/data.csv /import/archiv/data.csv']);
Vytvoření adresáře před uploadem:
curl.setOpt('QUOTE', ['mkdir /import/2026-11']);
Jen příkazy bez přenosu, například smazat soubor a nic nestahovat:
curl.start();
curl.setOpt('URL', 'sftp://sftp.example.com:22/export/');
curl.setOpt('USERPWD', 'uzivatel:heslo');
curl.setOpt('NOBODY', true);
curl.setOpt('QUOTE', ['rm /export/stary.csv']);
await curl.perform();
7. Ošetření chyb
curl.perform() při chybě vyhodí výjimku s textem chyby libcurl, například Couldn't connect to server, Login denied, Timeout was reached, Unsupported protocol, Access denied to remote resource (zápis bez práv) nebo Quote command returned error. Doporučený vzor:
try {
curl.start();
curl.setOpt('URL', 'sftp://sftp.example.com:22/export/data.csv');
curl.setOpt('USERPWD', 'uzivatel:heslo');
curl.setOpt('TIMEOUT', 120);
const { data } = await curl.perform();
vars['csvObsah'].setValue(data);
} catch (err) {
throw new Error('SFTP stažení selhalo: ' + err.message);
}
Chyba se tak zobrazí uživateli v úloze a zapíše do logu výpočtů.
8. Časté problémy
Projev |
Příčina a řešení |
|
URL začíná |
|
Špatné heslo nebo neencodované speciální znaky v URL. Použijte |
Stažený PDF je poškozený |
Chybí |
Druhý požadavek ve stejném výpočtu padá |
Chyba |
|
Účet nemá právo zápisu do cílové cesty nebo cílový adresář neexistuje. |
Upload velkého souboru skončí timeoutem |
Výchozí limit je 60 s, nastavte |
Upload do neexistujícího adresáře selže |
SFTP adresáře nevytváří, použijte |
9. Klasické FTP
Pro ftp:// URL je v 5.7 potřeba po curl.start() nastavit volbu PROTOCOLS_STR se seznamem protokolů. Bez ní skončí perform() chybou Unsupported protocol. Ověřeno na 5.7.105: výpis, upload, stažení zpět, MKD, přejmenování, DELE a RMD.
ftp API se tento kód přepíše podle kapitoly 10.Výpis adresáře a upload se liší od SFTP jen protokolem v URL a řádkem navíc:
curl.start();
curl.setOpt('PROTOCOLS_STR', 'ftp,sftp,http,https');
curl.setOpt('URL', 'ftp://ftp.example.com/import/' + encodeURIComponent('data.csv'));
curl.setOpt('USERPWD', 'uzivatel:heslo');
curl.setOpt('TIMEOUT', 300);
curl.setOpt('UPLOAD', true);
curl.sendBinaryBuffer(Buffer.from(csv, 'utf-8'));
const r = await curl.perform(); // r.statusCode je FTP kód odpovědi, např. 226
Příkazy pro QUOTE jsou u FTP klasické FTP příkazy, opět s absolutními cestami:
Operace |
SFTP |
FTP |
vytvoření adresáře |
|
|
přejmenování / přesun |
|
|
smazání souboru |
|
|
smazání adresáře |
|
|
curl.start();
curl.setOpt('PROTOCOLS_STR', 'ftp,sftp,http,https');
curl.setOpt('URL', 'ftp://ftp.example.com/import/');
curl.setOpt('USERPWD', 'uzivatel:heslo');
curl.setOpt('NOBODY', true);
curl.setOpt('QUOTE', ['MKD /import/archiv', 'RNFR /import/data.csv', 'RNTO /import/archiv/data.csv']);
await curl.perform();
10. Co se změní po upgradu
Od verze 5.12.22 je k dispozici ftp API, které umí i klasické FTP, a curl je v novějších verzích odstraněn. Kontrola šablony to před upgradem hlásí. Při přechodu z 5.7 stačí nahradit bloky curl.* voláním odpovídající metody klienta:
const client = ftp.getFtpClient({
protocol: 'sftp', // nebo 'ftp'
host: 'sftp.example.com',
port: 22,
username: 'uzivatel',
password: 'heslo',
});
await client.list('/export');
await client.upload(vars['priloha'], '/import/smlouva.pdf'); // zdroj je DMS soubor
await client.download('/export/data.csv'); // vrátí lokální cestu
await client.exists('/export/data.csv');
await client.delete('/export/data.csv');
await client.rename('/import/a.csv', '/import/archiv/a.csv');
await client.createDirectory('/import/2026-11', true);
await client.removeDirectory('/import/old', true);
Od verze 5.17 lze heslo předat z Trezoru přes ftp.getFtpClientWithVaultPassword(config, vault.get('nazev')). Kompletní popis nového API včetně povolených cest je v článku FTP a SFTP použití ve výpočtech.