88 lines
3.0 KiB
Markdown
88 lines
3.0 KiB
Markdown
|
# 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",
|
||
|
Data: config.File,
|
||
|
}}
|
||
|
|
||
|
// We'll only add a file if we have one.
|
||
|
if config.Thumb != nil {
|
||
|
files = append(files, RequestFile{
|
||
|
Name: "thumb",
|
||
|
Data: config.Thumb,
|
||
|
})
|
||
|
}
|
||
|
|
||
|
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
|
||
|
photo := tgbotapi.NewInputMediaPhoto(tgbotapi.FilePath("tests/image.jpg"))
|
||
|
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,
|
||
|
})
|
||
|
```
|
||
|
|
||
|
A `MediaGroupConfig` stores all of the media in an array of interfaces. We now
|
||
|
have all of the data we need to upload, but how do we figure out field names for
|
||
|
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.
|