Files: upload & download
Upload up to 4 GB on premium accounts (2 GB otherwise). Download with a worker pool. Stream files for transcoding pipelines. gogram handles MTProto's chunked file protocol so you do not have to.
Uploading
f, err := client.UploadFile("./big.zip", &telegram.UploadOptions{
Threads: 8,
ChunkSize: 512 * 1024,
ProgressCallback: func(p *telegram.ProgressInfo) {
fmt.Printf("%d / %d (%0.1f KB/s)\n", p.Current, p.TotalSize, p.CurrentSpeed/1024)
},
})
client.SendMedia(peerID, f, &telegram.MediaOptions{FileName: "big.zip"})f, err := client.UploadFile("./big.zip", &telegram.UploadOptions{
Threads: 8,
ChunkSize: 512 * 1024,
ProgressCallback: func(p *telegram.ProgressInfo) {
fmt.Printf("%d / %d (%0.1f KB/s)\n", p.Current, p.TotalSize, p.CurrentSpeed/1024)
},
})
client.SendMedia(peerID, f, &telegram.MediaOptions{FileName: "big.zip"})- 1
Threadsis the parallel-sender pool size. 8 is a sensible default; drop it for weak networks, don't raise it above ~10 or the DC will flood-wait you. - 2
ChunkSizedefaults to 512 KB below 10 MB and 1 MB above. Only override for weird MTU / proxy scenarios. - 3
ProgressCallbackfires periodically with byte counts and current speed. Cadence is controlled byProgressInterval— default ~5s. - 4The returned
InputFilecan be reused across multipleSendMediacalls without re-uploading.
Most of the time you do not need to call UploadFile directly. Pass a local path or a reader straight to SendMedia— the high-level helper inlines all of this. UploadFile is for when you want to upload once and reference the same file in multiple subsequent sends.
Downloading
path, err := client.DownloadMedia(msg, &telegram.DownloadOptions{
FileName: "./downloads/build.zip",
Threads: 8,
ProgressCallback: func(p *telegram.ProgressInfo) {
log.Printf("dl %d/%d", p.Current, p.TotalSize)
},
})path, err := client.DownloadMedia(msg, &telegram.DownloadOptions{
FileName: "./downloads/build.zip",
Threads: 8,
ProgressCallback: func(p *telegram.ProgressInfo) {
log.Printf("dl %d/%d", p.Current, p.TotalSize)
},
})DownloadMedia chunks the file in the opposite direction, one worker per thread. The return value is the path to the saved file (or empty when the download was streamed to your own buffer via DownloadOptions.Buffer).
Progress callbacks
Both upload and download accept a ProgressCallback that fires periodically with a *ProgressInfo carrying Current, TotalSize, CurrentSpeed (bytes per second over the last interval), and the file name. Tune the cadence with ProgressInterval— default is roughly every five seconds, which is enough for a CLI but rarely enough for a UI. Drop it to 1 second for a responsive progress bar.
File references
Telegram protects against media-id enumeration with file references: opaque tokens attached to every InputFileLocation that expire after a few hours. A long-stored InputDocument returns FILE_REFERENCE_EXPIREDwhen you try to download days later.
// re-fetch the message to get a fresh file reference, then try again
_, err := client.DownloadMedia(msg)
if err != nil && strings.Contains(err.Error(), "FILE_REFERENCE_EXPIRED") {
fresh, _ := client.GetMessageByID(msg.ChatID(), msg.ID)
_, err = client.DownloadMedia(fresh)
}// re-fetch the message to get a fresh file reference, then try again
_, err := client.DownloadMedia(msg)
if err != nil && strings.Contains(err.Error(), "FILE_REFERENCE_EXPIRED") {
fresh, _ := client.GetMessageByID(msg.ChatID(), msg.ID)
_, err = client.DownloadMedia(fresh)
}The fix is always the same: re-fetch the owning message (or sticker set, channel post, whatever holds the file) to get a fresh reference, then retry the download.
Threads and chunks
gogram maintains a pool of exported senders— one MTProto connection per worker, all sharing the same auth key but with their own sequence numbers. Threads: 8 is a sensible default; each thread pulls or pushes different chunk offsets in parallel. Higher values give diminishing returns and can trip FLOOD_WAITs if the DC is busy under load.
Size limits
- Max file size: 2 GB for free accounts, 4 GB for Premium.
- Max upload concurrency per DC: roughly 10 senders before flood waits kick in.
- Default per-chunk timeout: ~60 seconds; bump via the client's
ReqTimeoutif you regularly time out on slow links.
