<ahref="https://github.com/InsanusMokrassar/docs/edit/master/docs/tgbotapi/logic/files-handling.md"title="Edit this page"class="md-content__button md-icon">
<ahref="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">
<li>By <ahref="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 <ahref="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>
<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>
<h3id="where-to-get-file-id-or-url">Where to get File id or url?<aclass="headerlink"href="#where-to-get-file-id-or-url"title="Permanent link">¶</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 <ahref="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 <ahref="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>
val fileId = message.asCommonMessage() ?.withContent<MediaContent>() ?.content ?.media ?.fileId;
</code></pre>
<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<MediaContent>() ?.content</code> and then just get its media file id.</p>
<li>Download it in memory as <code>ByteArray</code></li>
<li>Take <code>ByteReadChannelAllocator</code> which allow to retrieve <ahref="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>
<h3id="downloading-with-api-extensions">Downloading with <code>API</code> extensions<aclass="headerlink"href="#downloading-with-api-extensions"title="Permanent link">¶</a></h3>
<p>See <ahref="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>
val tempFile: File = bot.downloadFileToTemp(fileId)
</code></pre>
<p>See <ahref="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>
val bytes: ByteReadChannelAllocator = bot.downloadFileStream(fileId)
</code></pre>
<p>See <ahref="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>
val bytes: ByteReadChannelAllocator = bot.downloadFileStreamAllocator(fileId)
</code></pre>
<p>See <ahref="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>
<p>See <ahref="https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.api.files/download-file.html">downloadFile</a> extension docs to get more available options</p>
<h3id="low-level-or-how-does-it-work">Low level or <code>how does it work?</code><aclass="headerlink"href="#low-level-or-how-does-it-work"title="Permanent link">¶</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>
val pathedFile: PathedFile = bot.execute(GetFile(fileId))
val downloadedBytes: ByteArray = bot.execute(DownloadFile(pathedFile.filePath))
</code></pre>
<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>
val pathedFile: PathedFile = bot.execute(GetFile(fileId))
val channelAllocator: ByteReadChannelAllocator = bot.execute(DownloadFileStream(pathedFile.filePath))
val byteReadChannel: ByteReadChannel = channelAllocator()
</code></pre>
<p>And then you may look into <ahref="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>
<p>Of course, in most cases you must be sure that file have correct type.</p>
<h2id="fileid-and-fileurl">FileId and FileUrl<aclass="headerlink"href="#fileid-and-fileurl"title="Permanent link">¶</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>
<h2id="sending-via-file">Sending via file<aclass="headerlink"href="#sending-via-file"title="Permanent link">¶</a></h2>
<divclass="admonition warning">
<pclass="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 <ahref="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 <ahref="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>
<scriptid="__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>