Skip to content

# Files handling

According to the documentation there are several ways to work with files:

- By FileId
- By FileUrl (`typealias` for the `FileId`)
- By some MultipartFile (in Telegram Bot API it is multipart requests)

# Files receiving

There are several cases you may need in your app to work with files:

- Save `FileId` (for sending in future)
- Download some file into memory/file in filesystem

### Where to get File id or url?

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 Message, you may use asCommonMessage conversation to be able to get its `content` and then convert it to some content with media. Full code here:

    val message: Message;

    val fileId = message.asCommonMessage() ?.withContent<MediaContent>() ?.content ?.media ?.fileId;

WAT? O.o

In the code above we get some message, safely converted it to `CommonMessage` with `asCommonMessage`, then safely took its content via `withContent<MediaContent>() ?.content` and then just get its media file id.

## Download files

There are three ways to download files:

- Download it in memory as `ByteArray`
- Take `ByteReadChannelAllocator` which allow to retrieve ByteReadChannel and do whatever you want with it
- `[JVM Only]` Download it directly to file or temporal file

### Downloading with `API` extensions

#### Files (JVM/Android)

    val bot: TelegramBot;
    val fileId: FileId;
    val outputFile: File;

    bot.downloadFile(fileId, outputFile)

See downloadFile extension docs in the JVM tab to get more available options

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:

    val bot: TelegramBot;
    val fileId: FileId;

    val tempFile: File = bot.downloadFileToTemp(fileId)

See downloadFileToTemp extension docs to get more available options

#### Byte read channel

    val bot: TelegramBot;
    val fileId: FileId;

    val bytes: ByteReadChannelAllocator = bot.downloadFileStream(fileId)

See downloadFileStream extension docs to get more available options

#### Byte read channel allocator

    val bot: TelegramBot;
    val fileId: FileId;

    val bytes: ByteReadChannelAllocator = bot.downloadFileStreamAllocator(fileId)

See downloadFileStreamAllocator extension docs to get more available options

#### Byte arrays

    val bot: TelegramBot;
    val fileId: FileId;

    val bytes: ByteArray = bot.downloadFile(fileId)

See downloadFile extension docs to get more available options

### Low level or `how does it work?`

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:

    val bot: TelegramBot;
    val fileId: FileId;

    val pathedFile: PathedFile = bot.execute(GetFile(fileId))

    val downloadedBytes: ByteArray = bot.execute(DownloadFile(pathedFile.filePath))

In the snippet above we are getting file `PathedFile` by its `FileId` and use it to download file bytes into memory using `DownloadFile` request.

You may use almost the same way but with byte read channel allocator:

    val bot: TelegramBot;
    val fileId: FileId;

    val pathedFile: PathedFile = bot.execute(GetFile(fileId))

    val channelAllocator: ByteReadChannelAllocator = bot.execute(DownloadFileStream(pathedFile.filePath))

    val byteReadChannel: ByteReadChannel = channelAllocator()

And then you may look into ByteReadChannel docs to get more info about what you can do with that.

Several useful links

- GetFile
- PathedFile
- DownloadFile
- DownloadFileStream

# Files sending

Of course, in most cases you must be sure that file have correct type.

## FileId and FileUrl

It is the most simple way to send any media in Telegram, but this way have several restrictions:

- The `FileId` which has retrieved for file should not (and probably will not too) equal to the `FileId` retrieved by some other bot
- There is a chance that the file id you are using will be expired with time

## Sending via file

JS Restrictions

Sending via file is accessible from all supported platforms, but there is small note about `JS` - due to restrictions of work with streams and stream-like data (`JS` 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.

Sending via file is available throw the MultipartFile. There are several wayt to get it:

- Simple creating via its constructor: `MultipartFile("filename.jpg") { /* here Input allocation */ }`
- Via asMultiparFile extension applicable to any `ByteArray`, `ByteReadChannel`, `ByteReadChannelAllocator` or `File` (on any platform)

In most cases, sending via files looks like in the next snippet:

    val file: File;

    bot.sendDocument(chatId, file.asMultipartFile())