docs/tgbotapi/logic/files-handling.html

1413 lines
52 KiB
HTML
Raw Normal View History

<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="Single documentation place for all Insanus Mokrassar libraries">
<meta name="author" content="Ovsiannikov Aleksei">
<link rel="canonical" href="https://docs.inmo.dev/tgbotapi/logic/files-handling.html">
<link rel="prev" href="exceptions-handling.html">
<link rel="next" href="low-level-work-with-bots.html">
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.4.3, mkdocs-material-9.1.15">
<title>Files handling - InMo Docs</title>
<link rel="stylesheet" href="../../assets/stylesheets/main.26e3688c.min.css">
<link rel="stylesheet" href="../../assets/stylesheets/palette.ecc896b0.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="teal" data-md-color-accent="cyan">
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#files-handling" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="../../index.html" title="InMo Docs" class="md-header__button md-logo" aria-label="InMo Docs" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
InMo Docs
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Files handling
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="" data-md-color-scheme="default" data-md-color-primary="teal" data-md-color-accent="cyan" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_2" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69Z"/></svg>
</label>
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="blue-grey" data-md-color-accent="light-blue" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_2">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_1" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12c0-2.42-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69Z"/></svg>
</label>
</form>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7 0-.24-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91 1.61 0 2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08Z"/></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header__source">
<a href="https://github.com/InsanusMokrassar/docs" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
</div>
<div class="md-source__repository">
InsanusMokrassar/docs
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="../../index.html" class="md-tabs__link">
Home
</a>
</li>
<li class="md-tabs__item">
<a href="../introduction/before-any-bot-project.html" class="md-tabs__link md-tabs__link--active">
Telegram Bot API
</a>
</li>
<li class="md-tabs__item">
<a href="../../krontab/introduction/including-in-project.html" class="md-tabs__link">
Krontab
</a>
</li>
<li class="md-tabs__item">
<a href="../../kslog/index.html" class="md-tabs__link">
KSLog
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="../../index.html" title="InMo Docs" class="md-nav__button md-logo" aria-label="InMo Docs" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>
</a>
InMo Docs
</label>
<div class="md-nav__source">
<a href="https://github.com/InsanusMokrassar/docs" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
</div>
<div class="md-source__repository">
InsanusMokrassar/docs
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../index.html" class="md-nav__link">
Home
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" checked>
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
Telegram Bot API
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
Telegram Bot API
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1" >
<label class="md-nav__link" for="__nav_2_1" id="__nav_2_1_label" tabindex="0">
Introduction
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_1_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2_1">
<span class="md-nav__icon md-icon"></span>
Introduction
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../introduction/before-any-bot-project.html" class="md-nav__link">
Before any bot project
</a>
</li>
<li class="md-nav__item">
<a href="../introduction/including-in-your-project.html" class="md-nav__link">
Including in your project
</a>
</li>
<li class="md-nav__item">
<a href="../introduction/proxy-setup.html" class="md-nav__link">
Proxy setup
</a>
</li>
<li class="md-nav__item">
<a href="../introduction/first-bot.html" class="md-nav__link">
First bot
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_2" >
<label class="md-nav__link" for="__nav_2_2" id="__nav_2_2_label" tabindex="0">
Updates retrieving
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2_2">
<span class="md-nav__icon md-icon"></span>
Updates retrieving
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../updates/updates-filters.html" class="md-nav__link">
Updates filters
</a>
</li>
<li class="md-nav__item">
<a href="../updates/long-polling.html" class="md-nav__link">
Long polling
</a>
</li>
<li class="md-nav__item">
<a href="../updates/webhooks.html" class="md-nav__link">
Webhooks
</a>
</li>
<li class="md-nav__item">
<a href="../updates/heroku.html" class="md-nav__link">
Heroku
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_3" checked>
<label class="md-nav__link" for="__nav_2_3" id="__nav_2_3_label" tabindex="0">
Logic handling
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_2_3">
<span class="md-nav__icon md-icon"></span>
Logic handling
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="api-extensions.html" class="md-nav__link">
API Extensions
</a>
</li>
<li class="md-nav__item">
<a href="behaviour-builder-with-fsm.html" class="md-nav__link">
Behaviour Builder with FSM
</a>
</li>
<li class="md-nav__item">
<a href="behaviour-builder.html" class="md-nav__link">
Behaviour Builder
</a>
</li>
<li class="md-nav__item">
<a href="exceptions-handling.html" class="md-nav__link">
Exceptions handling
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<a href="files-handling.html" class="md-nav__link md-nav__link--active">
Files handling
</a>
</li>
<li class="md-nav__item">
<a href="low-level-work-with-bots.html" class="md-nav__link">
Low-level work with bots
</a>
</li>
<li class="md-nav__item">
<a href="media-groups.html" class="md-nav__link">
Media Groups
</a>
</li>
<li class="md-nav__item">
<a href="types-conversations.html" class="md-nav__link">
Types conversations
</a>
</li>
<li class="md-nav__item">
<a href="updates-with-flows.html" class="md-nav__link">
Updates with flows
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_4" >
<label class="md-nav__link" for="__nav_2_4" id="__nav_2_4_label" tabindex="0">
DSLs
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2_4">
<span class="md-nav__icon md-icon"></span>
DSLs
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../dsls/keyboards.html" class="md-nav__link">
Keyboards
</a>
</li>
<li class="md-nav__item">
<a href="../dsls/live-location.html" class="md-nav__link">
Live Location
</a>
</li>
<li class="md-nav__item">
<a href="../dsls/text.html" class="md-nav__link">
Text
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
Krontab
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Krontab
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_1" >
<label class="md-nav__link" for="__nav_3_1" id="__nav_3_1_label" tabindex="0">
Introduction
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_1_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_1">
<span class="md-nav__icon md-icon"></span>
Introduction
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../krontab/introduction/including-in-project.html" class="md-nav__link">
Including in project
</a>
</li>
<li class="md-nav__item">
<a href="../../krontab/introduction/how-to-use.html" class="md-nav__link">
How to use
</a>
</li>
<li class="md-nav__item">
<a href="../../krontab/introduction/faq.html" class="md-nav__link">
FAQ
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_2" >
<label class="md-nav__link" for="__nav_3_2" id="__nav_3_2_label" tabindex="0">
Describing
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_2">
<span class="md-nav__icon md-icon"></span>
Describing
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../krontab/describing/string-format.html" class="md-nav__link">
String format
</a>
</li>
<li class="md-nav__item">
<a href="../../krontab/describing/krontabscheduler.html" class="md-nav__link">
KrontabScheduler
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4" >
<div class="md-nav__link md-nav__link--index ">
<a href="../../kslog/index.html">KSLog</a>
<label for="__nav_4">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
KSLog
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../kslog/setup.html" class="md-nav__link">
Setup
</a>
</li>
<li class="md-nav__item">
<a href="../../kslog/logging.html" class="md-nav__link">
Logging
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<a href="https://github.com/InsanusMokrassar/docs/edit/master/docs/tgbotapi/logic/files-handling.md" title="Edit this page" class="md-content__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M10 20H6V4h7v5h5v3.1l2-2V8l-6-6H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h4v-2m10.2-7c.1 0 .3.1.4.2l1.3 1.3c.2.2.2.6 0 .8l-1 1-2.1-2.1 1-1c.1-.1.2-.2.4-.2m0 3.9L14.1 23H12v-2.1l6.1-6.1 2.1 2.1Z"/></svg>
</a>
<a href="https://github.com/InsanusMokrassar/docs/raw/master/docs/tgbotapi/logic/files-handling.md" title="View source of this page" class="md-content__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 18c.56 0 1 .44 1 1s-.44 1-1 1-1-.44-1-1 .44-1 1-1m0-3c-2.73 0-5.06 1.66-6 4 .94 2.34 3.27 4 6 4s5.06-1.66 6-4c-.94-2.34-3.27-4-6-4m0 6.5a2.5 2.5 0 0 1-2.5-2.5 2.5 2.5 0 0 1 2.5-2.5 2.5 2.5 0 0 1 2.5 2.5 2.5 2.5 0 0 1-2.5 2.5M9.27 20H6V4h7v5h5v4.07c.7.08 1.36.25 2 .49V8l-6-6H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h4.5a8.15 8.15 0 0 1-1.23-2Z"/></svg>
</a>
<h1 id="files-handling">Files handling<a class="headerlink" href="#files-handling" title="Permanent link">&para;</a></h1>
<p>According to the <a href="https://core.telegram.org/bots/api#sending-files">documentation</a> there are several ways to work with files:</p>
<ul>
<li>By <a href="https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/abstracts/InputFile.kt#L52">FileId</a></li>
<li>By <a href="https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/abstracts/InputFile.kt#L56">FileUrl</a> (<code>typealias</code> for the <code>FileId</code>)</li>
<li>By some <a href="https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/abstracts/InputFile.kt#L74">MultipartFile</a> (in Telegram Bot API it is multipart requests)</li>
</ul>
<h1 id="files-receiving">Files receiving<a class="headerlink" href="#files-receiving" title="Permanent link">&para;</a></h1>
<p>There are several cases you may need in your app to work with files:</p>
<ul>
<li>Save <code>FileId</code> (for sending in future)</li>
<li>Download some file into memory/file in filesystem</li>
</ul>
<h3 id="where-to-get-file-id-or-url">Where to get File id or url?<a class="headerlink" href="#where-to-get-file-id-or-url" title="Permanent link">&para;</a></h3>
<p>The most simple way to send some file is to get file id and send it. You may get file id from any message with media. For example, if you have received some <a href="https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/abstracts/Message.kt#L12">Message</a>, you may use <a href="https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCasts.kt#L1094">asCommonMessage</a> conversation to be able to get its <code>content</code> and then convert it to some content with media. Full code here:</p>
<div class="language-kotlin highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="kd">val</span><span class="w"> </span><span class="nv">message</span><span class="p">:</span><span class="w"> </span><span class="n">Message</span><span class="p">;</span>
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a>
</span><span id="__span-0-3"><a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="kd">val</span><span class="w"> </span><span class="nv">fileId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">message</span><span class="p">.</span><span class="na">asCommonMessage</span><span class="p">()</span><span class="w"> </span><span class="o">?.</span><span class="na">withContent</span><span class="o">&lt;</span><span class="n">MediaContent</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="o">?.</span><span class="na">content</span><span class="w"> </span><span class="o">?.</span><span class="na">media</span><span class="w"> </span><span class="o">?.</span><span class="na">fileId</span><span class="p">;</span>
</span></code></pre></div>
<p><strong>WAT? O.o</strong></p>
<p>In the code above we get some message, safely converted it to <code>CommonMessage</code> with <code>asCommonMessage</code>, then safely took its content via <code>withContent&lt;MediaContent&gt;() ?.content</code> and then just get its media file id.</p>
<h2 id="download-files">Download files<a class="headerlink" href="#download-files" title="Permanent link">&para;</a></h2>
<p>There are three ways to download files:</p>
<ul>
<li>Download it in memory as <code>ByteArray</code></li>
<li>Take <code>ByteReadChannelAllocator</code> which allow to retrieve <a href="https://api.ktor.io/ktor-io/io.ktor.utils.io/-byte-read-channel/index.html">ByteReadChannel</a> and do whatever you want with it</li>
<li><code>[JVM Only]</code> Download it directly to file or temporal file</li>
</ul>
<h3 id="downloading-with-api-extensions">Downloading with <code>API</code> extensions<a class="headerlink" href="#downloading-with-api-extensions" title="Permanent link">&para;</a></h3>
<h4 id="files-jvmandroid">Files (JVM/Android)<a class="headerlink" href="#files-jvmandroid" title="Permanent link">&para;</a></h4>
<div class="language-kotlin highlight"><pre><span></span><code><span id="__span-1-1"><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a><span class="kd">val</span><span class="w"> </span><span class="nv">bot</span><span class="p">:</span><span class="w"> </span><span class="n">TelegramBot</span><span class="p">;</span>
</span><span id="__span-1-2"><a id="__codelineno-1-2" name="__codelineno-1-2" href="#__codelineno-1-2"></a><span class="kd">val</span><span class="w"> </span><span class="nv">fileId</span><span class="p">:</span><span class="w"> </span><span class="n">FileId</span><span class="p">;</span>
</span><span id="__span-1-3"><a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a><span class="kd">val</span><span class="w"> </span><span class="nv">outputFile</span><span class="p">:</span><span class="w"> </span><span class="n">File</span><span class="p">;</span>
</span><span id="__span-1-4"><a id="__codelineno-1-4" name="__codelineno-1-4" href="#__codelineno-1-4"></a>
</span><span id="__span-1-5"><a id="__codelineno-1-5" name="__codelineno-1-5" href="#__codelineno-1-5"></a><span class="n">bot</span><span class="p">.</span><span class="na">downloadFile</span><span class="p">(</span><span class="n">fileId</span><span class="p">,</span><span class="w"> </span><span class="n">outputFile</span><span class="p">)</span>
</span></code></pre></div>
<p>See <a href="https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.api.files/download-file.html">downloadFile</a> extension docs in the <strong>JVM tab</strong> to get more available options</p>
<p>There is also way with saving of data into temporal file. That will allow you to do with data whatever you want without high requirements to memory or network connection:</p>
<div class="language-kotlin highlight"><pre><span></span><code><span id="__span-2-1"><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a><span class="kd">val</span><span class="w"> </span><span class="nv">bot</span><span class="p">:</span><span class="w"> </span><span class="n">TelegramBot</span><span class="p">;</span>
</span><span id="__span-2-2"><a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a><span class="kd">val</span><span class="w"> </span><span class="nv">fileId</span><span class="p">:</span><span class="w"> </span><span class="n">FileId</span><span class="p">;</span>
</span><span id="__span-2-3"><a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a>
</span><span id="__span-2-4"><a id="__codelineno-2-4" name="__codelineno-2-4" href="#__codelineno-2-4"></a><span class="kd">val</span><span class="w"> </span><span class="nv">tempFile</span><span class="p">:</span><span class="w"> </span><span class="n">File</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bot</span><span class="p">.</span><span class="na">downloadFileToTemp</span><span class="p">(</span><span class="n">fileId</span><span class="p">)</span>
</span></code></pre></div>
<p>See <a href="https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.api.files/download-file-to-temp.html">downloadFileToTemp</a> extension docs to get more available options</p>
<h4 id="byte-read-channel">Byte read channel<a class="headerlink" href="#byte-read-channel" title="Permanent link">&para;</a></h4>
<div class="language-kotlin highlight"><pre><span></span><code><span id="__span-3-1"><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a><span class="kd">val</span><span class="w"> </span><span class="nv">bot</span><span class="p">:</span><span class="w"> </span><span class="n">TelegramBot</span><span class="p">;</span>
</span><span id="__span-3-2"><a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a><span class="kd">val</span><span class="w"> </span><span class="nv">fileId</span><span class="p">:</span><span class="w"> </span><span class="n">FileId</span><span class="p">;</span>
</span><span id="__span-3-3"><a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a>
</span><span id="__span-3-4"><a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a><span class="kd">val</span><span class="w"> </span><span class="nv">bytes</span><span class="p">:</span><span class="w"> </span><span class="n">ByteReadChannelAllocator</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bot</span><span class="p">.</span><span class="na">downloadFileStream</span><span class="p">(</span><span class="n">fileId</span><span class="p">)</span>
</span></code></pre></div>
<p>See <a href="https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.api.files/download-file-stream.html">downloadFileStream</a> extension docs to get more available options</p>
<h4 id="byte-read-channel-allocator">Byte read channel allocator<a class="headerlink" href="#byte-read-channel-allocator" title="Permanent link">&para;</a></h4>
<div class="language-kotlin highlight"><pre><span></span><code><span id="__span-4-1"><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a><span class="kd">val</span><span class="w"> </span><span class="nv">bot</span><span class="p">:</span><span class="w"> </span><span class="n">TelegramBot</span><span class="p">;</span>
</span><span id="__span-4-2"><a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a><span class="kd">val</span><span class="w"> </span><span class="nv">fileId</span><span class="p">:</span><span class="w"> </span><span class="n">FileId</span><span class="p">;</span>
</span><span id="__span-4-3"><a id="__codelineno-4-3" name="__codelineno-4-3" href="#__codelineno-4-3"></a>
</span><span id="__span-4-4"><a id="__codelineno-4-4" name="__codelineno-4-4" href="#__codelineno-4-4"></a><span class="kd">val</span><span class="w"> </span><span class="nv">bytes</span><span class="p">:</span><span class="w"> </span><span class="n">ByteReadChannelAllocator</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bot</span><span class="p">.</span><span class="na">downloadFileStreamAllocator</span><span class="p">(</span><span class="n">fileId</span><span class="p">)</span>
</span></code></pre></div>
<p>See <a href="https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.api.files/download-file-stream-allocator.html">downloadFileStreamAllocator</a> extension docs to get more available options</p>
<h4 id="byte-arrays">Byte arrays<a class="headerlink" href="#byte-arrays" title="Permanent link">&para;</a></h4>
<div class="language-kotlin highlight"><pre><span></span><code><span id="__span-5-1"><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="kd">val</span><span class="w"> </span><span class="nv">bot</span><span class="p">:</span><span class="w"> </span><span class="n">TelegramBot</span><span class="p">;</span>
</span><span id="__span-5-2"><a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a><span class="kd">val</span><span class="w"> </span><span class="nv">fileId</span><span class="p">:</span><span class="w"> </span><span class="n">FileId</span><span class="p">;</span>
</span><span id="__span-5-3"><a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a>
</span><span id="__span-5-4"><a id="__codelineno-5-4" name="__codelineno-5-4" href="#__codelineno-5-4"></a><span class="kd">val</span><span class="w"> </span><span class="nv">bytes</span><span class="p">:</span><span class="w"> </span><span class="n">ByteArray</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bot</span><span class="p">.</span><span class="na">downloadFile</span><span class="p">(</span><span class="n">fileId</span><span class="p">)</span>
</span></code></pre></div>
<p>See <a href="https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.api.files/download-file.html">downloadFile</a> extension docs to get more available options</p>
<h3 id="low-level-or-how-does-it-work">Low level or <code>how does it work?</code><a class="headerlink" href="#low-level-or-how-does-it-work" title="Permanent link">&para;</a></h3>
<p>You may download file with streams or with downloading into the memory first. On low level you should do several things. They are presented in next snippet:</p>
<div class="language-kotlin highlight"><pre><span></span><code><span id="__span-6-1"><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a><span class="kd">val</span><span class="w"> </span><span class="nv">bot</span><span class="p">:</span><span class="w"> </span><span class="n">TelegramBot</span><span class="p">;</span>
</span><span id="__span-6-2"><a id="__codelineno-6-2" name="__codelineno-6-2" href="#__codelineno-6-2"></a><span class="kd">val</span><span class="w"> </span><span class="nv">fileId</span><span class="p">:</span><span class="w"> </span><span class="n">FileId</span><span class="p">;</span>
</span><span id="__span-6-3"><a id="__codelineno-6-3" name="__codelineno-6-3" href="#__codelineno-6-3"></a>
</span><span id="__span-6-4"><a id="__codelineno-6-4" name="__codelineno-6-4" href="#__codelineno-6-4"></a><span class="kd">val</span><span class="w"> </span><span class="nv">pathedFile</span><span class="p">:</span><span class="w"> </span><span class="n">PathedFile</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bot</span><span class="p">.</span><span class="na">execute</span><span class="p">(</span><span class="n">GetFile</span><span class="p">(</span><span class="n">fileId</span><span class="p">))</span>
</span><span id="__span-6-5"><a id="__codelineno-6-5" name="__codelineno-6-5" href="#__codelineno-6-5"></a>
</span><span id="__span-6-6"><a id="__codelineno-6-6" name="__codelineno-6-6" href="#__codelineno-6-6"></a><span class="kd">val</span><span class="w"> </span><span class="nv">downloadedBytes</span><span class="p">:</span><span class="w"> </span><span class="n">ByteArray</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bot</span><span class="p">.</span><span class="na">execute</span><span class="p">(</span><span class="n">DownloadFile</span><span class="p">(</span><span class="n">pathedFile</span><span class="p">.</span><span class="na">filePath</span><span class="p">))</span>
</span></code></pre></div>
<p>In the snippet above we are getting file <code>PathedFile</code> by its <code>FileId</code> and use it to download file bytes into memory using <code>DownloadFile</code> request.</p>
<p>You may use almost the same way but with byte read channel allocator:</p>
<div class="language-kotlin highlight"><pre><span></span><code><span id="__span-7-1"><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a><span class="kd">val</span><span class="w"> </span><span class="nv">bot</span><span class="p">:</span><span class="w"> </span><span class="n">TelegramBot</span><span class="p">;</span>
</span><span id="__span-7-2"><a id="__codelineno-7-2" name="__codelineno-7-2" href="#__codelineno-7-2"></a><span class="kd">val</span><span class="w"> </span><span class="nv">fileId</span><span class="p">:</span><span class="w"> </span><span class="n">FileId</span><span class="p">;</span>
</span><span id="__span-7-3"><a id="__codelineno-7-3" name="__codelineno-7-3" href="#__codelineno-7-3"></a>
</span><span id="__span-7-4"><a id="__codelineno-7-4" name="__codelineno-7-4" href="#__codelineno-7-4"></a><span class="kd">val</span><span class="w"> </span><span class="nv">pathedFile</span><span class="p">:</span><span class="w"> </span><span class="n">PathedFile</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bot</span><span class="p">.</span><span class="na">execute</span><span class="p">(</span><span class="n">GetFile</span><span class="p">(</span><span class="n">fileId</span><span class="p">))</span>
</span><span id="__span-7-5"><a id="__codelineno-7-5" name="__codelineno-7-5" href="#__codelineno-7-5"></a>
</span><span id="__span-7-6"><a id="__codelineno-7-6" name="__codelineno-7-6" href="#__codelineno-7-6"></a><span class="kd">val</span><span class="w"> </span><span class="nv">channelAllocator</span><span class="p">:</span><span class="w"> </span><span class="n">ByteReadChannelAllocator</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bot</span><span class="p">.</span><span class="na">execute</span><span class="p">(</span><span class="n">DownloadFileStream</span><span class="p">(</span><span class="n">pathedFile</span><span class="p">.</span><span class="na">filePath</span><span class="p">))</span>
</span><span id="__span-7-7"><a id="__codelineno-7-7" name="__codelineno-7-7" href="#__codelineno-7-7"></a>
</span><span id="__span-7-8"><a id="__codelineno-7-8" name="__codelineno-7-8" href="#__codelineno-7-8"></a><span class="kd">val</span><span class="w"> </span><span class="nv">byteReadChannel</span><span class="p">:</span><span class="w"> </span><span class="n">ByteReadChannel</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">channelAllocator</span><span class="p">()</span>
</span></code></pre></div>
<p>And then you may look into <a href="https://api.ktor.io/ktor-io/io.ktor.utils.io/-byte-read-channel/index.html">ByteReadChannel</a> docs to get more info about what you can do with that.</p>
<div class="admonition note">
<p class="admonition-title">Several useful links</p>
<ul>
<li><a href="" title="https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.requests.get/-get-file/index.html">GetFile</a></li>
<li><a href="" title="https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.types.files/-pathed-file/index.html">PathedFile</a></li>
<li><a href="" title="https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.requests/-download-file/index.html">DownloadFile</a></li>
<li><a href="" title="https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.requests/-download-file-stream/index.html">DownloadFileStream</a></li>
</ul>
</div>
<h1 id="files-sending">Files sending<a class="headerlink" href="#files-sending" title="Permanent link">&para;</a></h1>
<p>Of course, in most cases you must be sure that file have correct type.</p>
<h2 id="fileid-and-fileurl">FileId and FileUrl<a class="headerlink" href="#fileid-and-fileurl" title="Permanent link">&para;</a></h2>
<p>It is the most simple way to send any media in Telegram, but this way have several restrictions:</p>
<ul>
<li>The <code>FileId</code> which has retrieved for file should not (and probably will not too) equal to the <code>FileId</code> retrieved by some other bot</li>
<li>There is a chance that the file id you are using will be expired with time</li>
</ul>
<h2 id="sending-via-file">Sending via file<a class="headerlink" href="#sending-via-file" title="Permanent link">&para;</a></h2>
<div class="admonition warning">
<p class="admonition-title">JS Restrictions</p>
<p>
Sending via file is accessible from all supported platforms, but there is small note about <code>JS</code> - due to restrictions of work with streams and stream-like data (<code>JS</code> have no native support of files streaming) on this platform all the files will be loaded inside of RAM before the sending to the telegram services.</p>
</div>
<p>Sending via file is available throw the <a href="https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.requests.abstracts/-multipart-file/index.html">MultipartFile</a>. There are several wayt to get it:</p>
<ul>
<li>Simple creating via its constructor: <code>MultipartFile("filename.jpg") { /* here Input allocation */ }</code></li>
<li>Via <a href="https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.requests.abstracts/as-multipart-file.html">asMultiparFile</a> extension applicable to any <code>ByteArray</code>, <code>ByteReadChannel</code>, <code>ByteReadChannelAllocator</code> or <code>File</code> (on any platform)</li>
</ul>
<p>In most cases, sending via files looks like in the next snippet:</p>
<div class="language-kotlin highlight"><pre><span></span><code><span id="__span-8-1"><a id="__codelineno-8-1" name="__codelineno-8-1" href="#__codelineno-8-1"></a><span class="kd">val</span><span class="w"> </span><span class="nv">file</span><span class="p">:</span><span class="w"> </span><span class="n">File</span><span class="p">;</span>
</span><span id="__span-8-2"><a id="__codelineno-8-2" name="__codelineno-8-2" href="#__codelineno-8-2"></a>
</span><span id="__span-8-3"><a id="__codelineno-8-3" name="__codelineno-8-3" href="#__codelineno-8-3"></a><span class="n">bot</span><span class="p">.</span><span class="na">sendDocument</span><span class="p">(</span><span class="n">chatId</span><span class="p">,</span><span class="w"> </span><span class="n">file</span><span class="p">.</span><span class="na">asMultipartFile</span><span class="p">())</span>
</span></code></pre></div>
</article>
</div>
</div>
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12Z"/></svg>
Back to top
</button>
</main>
<footer class="md-footer">
<nav class="md-footer__inner md-grid" aria-label="Footer" >
<a href="exceptions-handling.html" class="md-footer__link md-footer__link--prev" aria-label="Previous: Exceptions handling" rel="prev">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</div>
<div class="md-footer__title">
<span class="md-footer__direction">
Previous
</span>
<div class="md-ellipsis">
Exceptions handling
</div>
</div>
</a>
<a href="low-level-work-with-bots.html" class="md-footer__link md-footer__link--next" aria-label="Next: Low-level work with bots" rel="next">
<div class="md-footer__title">
<span class="md-footer__direction">
Next
</span>
<div class="md-ellipsis">
Low-level work with bots
</div>
</div>
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"/></svg>
</div>
</a>
</nav>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "../..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.footer", "navigation.indexes", "navigation.sections", "navigation.tabs", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../../assets/javascripts/workers/search.208ed371.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script src="../../assets/javascripts/bundle.b4d07000.min.js"></script>
</body>
</html>