telegram-bot-api/docs/internals/uploading-files.md

88 lines
3.0 KiB
Markdown
Raw Permalink Normal View History

2020-07-27 00:22:16 +02:00
# Uploading Files
To make files work as expected, there's a lot going on behind the scenes. Make
sure to read through the [Files](../getting-started/files.md) section in
Getting Started first as we'll be building on that information.
This section only talks about file uploading. For non-uploaded files such as
URLs and file IDs, you just need to pass a string.
## Fields
Let's start by talking about how the library represents files as part of a
Config.
### Static Fields
Most endpoints use static file fields. For example, `sendPhoto` expects a single
file named `photo`. All we have to do is set that single field with the correct
value (either a string or multipart file). Methods like `sendDocument` take two
file uploads, a `document` and a `thumb`. These are pretty straightforward.
Remembering that the `Fileable` interface only requires one method, let's
implement it for `DocumentConfig`.
```go
func (config DocumentConfig) files() []RequestFile {
// We can have multiple files, so we'll create an array. We also know that
// there always is a document file, so initialize the array with that.
files := []RequestFile{{
Name: "document",
2021-08-20 22:15:37 +02:00
Data: config.File,
2020-07-27 00:22:16 +02:00
}}
// We'll only add a file if we have one.
if config.Thumb != nil {
files = append(files, RequestFile{
Name: "thumb",
2021-08-20 22:15:37 +02:00
Data: config.Thumb,
2020-07-27 00:22:16 +02:00
})
}
return files
}
```
Telegram also supports the `attach://` syntax (discussed more later) for
thumbnails, but there's no reason to make things more complicated.
### Dynamic Fields
Of course, not everything can be so simple. Methods like `sendMediaGroup`
can accept many files, and each file can have custom markup. Using a static
field isn't possible because we need to specify which field is attached to each
item. Telegram introduced the `attach://` syntax for this.
Let's follow through creating a new media group with string and file uploads.
First, we start by creating some `InputMediaPhoto`.
```go
2021-08-20 22:15:37 +02:00
photo := tgbotapi.NewInputMediaPhoto(tgbotapi.FilePath("tests/image.jpg"))
2020-07-27 00:22:16 +02:00
url := tgbotapi.NewInputMediaPhoto(tgbotapi.FileURL("https://i.imgur.com/unQLJIb.jpg"))
```
This created a new `InputMediaPhoto` struct, with a type of `photo` and the
media interface that we specified.
We'll now create our media group with the photo and URL.
```go
mediaGroup := NewMediaGroup(ChatID, []interface{}{
photo,
url,
})
```
2022-10-19 10:58:52 +02:00
A `MediaGroupConfig` stores all the media in an array of interfaces. We now
have all the data we need to upload, but how do we figure out field names for
2020-07-27 00:22:16 +02:00
uploads? We didn't specify `attach://unique-file` anywhere.
When the library goes to upload the files, it looks at the `params` and `files`
for the Config. The params are generated by transforming the file into a value
more suitable for uploading, file IDs and URLs are untouched but uploaded types
are all changed into `attach://file-%d`. When collecting a list of files to
upload, it names them the same way. This creates a nearly transparent way of
handling multiple files in the background without the user having to consider
what's going on.