When working with the API, it is sometimes necessary to send a relatively large file to the server. For example, when sending a message with a photo/video attachment or when setting the current user's profile picture.
There are a number of API methods to save files. The schema of the types and methods used is presented below:
inputFile#f52ff27f id:long parts:int name:string md5_checksum:string = InputFile;
inputFileBig#fa4f0bb5 id:long parts:int name:string = InputFile;
inputEncryptedFileUploaded#64bd0306 id:long parts:int md5_checksum:string key_fingerprint:int = InputEncryptedFile;
inputEncryptedFileBigUploaded#2dc173c8 id:long parts:int key_fingerprint:int = InputEncryptedFile;
inputSecureFileUploaded#3334b0f0 id:long parts:int md5_checksum:string file_hash:bytes secret:bytes = InputSecureFile;
inputSecureFile#5367e5be id:long access_hash:long = InputSecureFile;
inputMediaUploadedPhoto#1e287d04 flags:# file:InputFile stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
inputMediaUploadedDocument#5b38c6c1 flags:# nosound_video:flags.3?true force_file:flags.4?true file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector<DocumentAttribute> stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
inputChatUploadedPhoto#c642724e flags:# file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double = InputChatPhoto;
---functions---
messages.sendMedia#e25ff8e0 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
messages.uploadMedia#519bc2b1 peer:InputPeer media:InputMedia = MessageMedia;
messages.sendEncryptedFile#5559481d flags:# silent:flags.0?true peer:InputEncryptedChat random_id:long data:bytes file:InputEncryptedFile = messages.SentEncryptedMessage;
photos.uploadProfilePhoto#89f30f69 flags:# file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double = photos.Photo;
upload.saveFilePart#b304a621 file_id:long file_part:int bytes:bytes = Bool;
upload.saveBigFilePart#de7b673d file_id:long file_part:int file_total_parts:int bytes:bytes = Bool;
Before transmitting the contents of the file itself, the file has to be assigned a unique 64-bit client identifier: file_id.
The file's binary content is then split into parts. All parts must have the same size ( part_size ) and the following conditions must be met:
part_size % 1024 = 0
(divisible by 1KB)524288 % part_size = 0
(512KB must be evenly divisible by part_size)The last part does not have to satisfy these conditions, provided its size is less than part_size.
Each part should have a sequence number, file_part, with a value ranging from 0 to 2,999.
After the file has been partitioned you need to choose a method for saving it on the server. Use upload.saveBigFilePart in case the full size of the file is more than 10 MB and upload.saveFilePart for smaller files.
Each call saves a portion of the data in a temporary location on the server to be used later. The storage life of each portion of data is between several minutes and several hours (depending on how busy the storage area is). After this time, the file part will become unavailable. To increase the time efficiency of a file save operation, we recommend using a call queue, so X pieces of the file are being saved at any given moment in time. Each successful operation to save a part invokes the method call to save the next part. The value of X can be tuned to achieve maximum performance.
When using one of the methods mentioned above to save file parts, one of the following data input errors may be returned:
1..3000
0 and 2,999
.While the parts are being uploaded, an MD5 hash of the file contents can also be computed to be used later as the md5_checksum parameter in the inputFile constructor (since it is checked only by the server, for encrypted secret chat files it must be generated from the encrypted file). After the entire file is successfully saved, the final method may be called and passed the generated inputFile object. In case the upload.saveBigFilePart method is used, the inputFileBig constructor must be passed, in other cases use inputFile.
The file save operation may return one of the following data input errors:
inputMediaUploadedPhoto#1e287d04 flags:# file:InputFile stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
inputMediaUploadedDocument#5b38c6c1 flags:# nosound_video:flags.3?true force_file:flags.4?true file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector<DocumentAttribute> stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
inputSingleMedia#1cc6e91f flags:# media:InputMedia random_id:long message:string entities:flags.0?Vector<MessageEntity> = InputSingleMedia;
---functions---
messages.sendMultiMedia#f803138f flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true peer:InputPeer reply_to_msg_id:flags.0?int multi_media:Vector<InputSingleMedia> schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
Telegram allows grouping photos into albums and generic files (audio, docuemnts) into media groups.
To do this, messages.sendMultiMedia is used, wrapping each InputMedia constructor (uploaded or pre-existing, maximum 10 per media group) into an inputSingleMedia constructor, optionally providing a custom per-file caption in message
.
For photo albums, clients should display an album caption only if exactly one photo in the group has a caption, otherwise no album caption should be displayed, and only when viewing in detail a specific photo of the group the caption should be shown.
Other grouped media can display a caption under each file.
document#1e87342b flags:# id:long access_hash:long file_reference:bytes date:int mime_type:string size:int thumbs:flags.0?Vector<PhotoSize> video_thumbs:flags.1?Vector<VideoSize> dc_id:int attributes:Vector<DocumentAttribute> = Document;
---functions---
messages.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document;
For some types of documents like GIFs, messages.getDocumentByHash can be used to search for the document on Telegram servers. The SHA256 hash of the file is computed, and it is passed along with the file's mime type and size to the method: if the file type is correct and the file is found, a document is returned.
photo#fb197a65 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector<PhotoSize> video_sizes:flags.1?Vector<VideoSize> dc_id:int = Photo;
photos.photo#20212ca8 photo:Photo users:Vector<User> = photos.Photo;
inputPhoto#3bb3b94a id:long access_hash:long file_reference:bytes = InputPhoto;
inputFile#f52ff27f id:long parts:int name:string md5_checksum:string = InputFile;
inputChatUploadedPhoto#c642724e flags:# file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double = InputChatPhoto;
inputChatPhoto#8953ad37 id:InputPhoto = InputChatPhoto;
---functions---
photos.updateProfilePhoto#72d4742c id:InputPhoto = photos.Photo;
photos.uploadProfilePhoto#89f30f69 flags:# file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double = photos.Photo;
messages.editChatPhoto#35ddd674 chat_id:long photo:InputChatPhoto = Updates;
channels.editPhoto#f12e57c9 channel:InputChannel photo:InputChatPhoto = Updates;
User profile pictures can be uploaded using the photos.uploadProfilePhoto method: the actual profile picture has to be uploaded as for normal files.
photos.uploadProfilePhoto can also be used to reupload previously uploaded profile pictures.
Animated profile pictures are also supported, by populating the video
constructor: square MPEG4 videos up to 1080x1080
are supported, 800x800
is the recommended resolution.
The video_start_ts
is a floating point UNIX timestamp in seconds, indicating the frame of the video that should be used as static preview.
Chat, channel and supergroup profile photos and videos can be uploaded using messages.editChatPhoto (legacy groups) or channels.editPhoto (channels, supergroups).
Use the inputChatPhoto to reuse previously uploaded profile pictures.
There are methods available to download files which have been successfully uploaded. The schema of the types and methods used is presented below:
upload.file#96a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File;
upload.fileCdnRedirect#f18cda44 dc_id:int file_token:bytes encryption_key:bytes encryption_iv:bytes file_hashes:Vector<FileHash> = upload.File;
storage.fileUnknown#aa963b05 = storage.FileType;
storage.fileJpeg#7efe0e = storage.FileType;
storage.fileGif#cae1aadf = storage.FileType;
storage.filePng#a4f63c0 = storage.FileType;
storage.fileMp3#528a0677 = storage.FileType;
storage.fileMov#4b09ebbc = storage.FileType;
storage.filePartial#40bc6f52 = storage.FileType;
storage.fileMp4#b3cea0e4 = storage.FileType;
storage.fileWebp#1081464c = storage.FileType;
---functions---
upload.getFile#b15a9afc flags:# precise:flags.0?true cdn_supported:flags.1?true location:InputFileLocation offset:int limit:int = upload.File;
Any file can be downloaded by calling upload.getFile. The data for the input parameter of the InputFileLocation type is generated as follows:
inputFileLocation#dfdaabe1 volume_id:long local_id:int secret:long file_reference:bytes = InputFileLocation;
inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation;
inputDocumentFileLocation#bad07584 id:long access_hash:long file_reference:bytes thumb_size:string = InputFileLocation;
inputSecureFileLocation#cbc7ee28 id:long access_hash:long = InputFileLocation;
inputTakeoutFileLocation#29be5899 = InputFileLocation;
inputPhotoFileLocation#40181ffe id:long access_hash:long file_reference:bytes thumb_size:string = InputFileLocation;
inputPhotoLegacyFileLocation#d83466f3 id:long access_hash:long file_reference:bytes volume_id:long local_id:int secret:long = InputFileLocation;
inputPeerPhotoFileLocation#37257e99 flags:# big:flags.0?true peer:InputPeer photo_id:long = InputFileLocation;
inputStickerSetThumb#9d84f3db stickerset:InputStickerSet thumb_version:int = InputFileLocation;
inputGroupCallStream#598a92a flags:# call:InputGroupCall time_ms:long scale:int video_channel:flags.0?int video_quality:flags.0?int = InputFileLocation;
inputStickerSetEmpty#ffb62b95 = InputStickerSet;
inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
inputStickerSetAnimatedEmoji#28703c8 = InputStickerSet;
inputStickerSetDice#e67f520e emoticon:string = InputStickerSet;
inputStickerSetAnimatedEmojiAnimations#cde3739 = InputStickerSet;
inputPeerSelf#7da07ec9 = InputPeer;
inputPeerChat#35a95cb9 chat_id:long = InputPeer;
inputPeerUser#dde8a54c user_id:long access_hash:long = InputPeer;
inputPeerChannel#27bcbbfc channel_id:long access_hash:long = InputPeer;
photo#fb197a65 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector<PhotoSize> video_sizes:flags.1?Vector<VideoSize> dc_id:int = Photo;
document#1e87342b flags:# id:long access_hash:long file_reference:bytes date:int mime_type:string size:int thumbs:flags.0?Vector<PhotoSize> video_thumbs:flags.1?Vector<VideoSize> dc_id:int attributes:Vector<DocumentAttribute> = Document;
photoSize#75c78e60 type:string w:int h:int size:int = PhotoSize;
photoCachedSize#21e1ad6 type:string w:int h:int bytes:bytes = PhotoSize;
chatPhoto#1c6e1c11 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = ChatPhoto;
userProfilePhoto#82d1f706 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto;
For photos, inputPhotoFileLocation is used:
For profile pictures of users, channels, supergroups and groups, inputPeerPhotoFileLocation has to be used:
peer
is the identifier of the peer whose photo we want to downloadbig
is used to choose whether to download the full-resolution picture, or just the thumbnailphoto_id
is extracted from the chatPhoto or userProfilePhoto of the desired profile photoFor documents, inputDocumentFileLocation is used:
For previews of sticker sets, inputStickerSetThumb is used (note: to download stickers and previews of stickers use the document method described above for documents):
stickerset
is set to the InputStickerSet constructor generated from stickerSetthumb_version
is copied from the same field in stickerSetFor encrypted secret chat and telegram passport documents, respectively inputEncryptedFileLocation and inputSecureFileLocation have to be used, with parameters extracted from encryptedFile and secureFile (passport docs).
For livestream chunks, inputGroupCallStream is used:
call
contains the related group call ID+access hash, taken from the groupCall constructor.time_ms
specifies the timestamp to fetchscale
specifies the duration of the video segment to fetch in milliseconds, by bitshifting 1000
to the right scale
times: duration_ms := 1000 >> scale
video_channel
specifies the video channel to fetchvideo_quality
specifies the selected video quality (0 = lowest, 1 = medium, 2 = best)For old deprecated photos, if the client has cached some old fileLocations with the deprecated secret
identifier, inputFileLocation or inputPhotoLegacyFileLocation is used (this is mainly used for backwards compatiblity with bot API file IDs, all user clients must use the modern inputPhotoFileLocation file IDs):
file_reference
, access_hash
and id
, which are taken from the photo constructor (the last two fields are used only if available, in which case inputPhotoLegacyFileLocation is used instead of inputFileLocation).The size of each file in bytes is available, which makes it possible to download the file in parts using the parameters offset and limit, similar to the way files are uploaded.
If precise flag is not specified, then
If precise is specified, then
In any case the requested part should be within one 1 MB chunk from the beginning of the file, i. e.
The file download operation may return a FILE_REFERENCE_EXPIRED
error (or another error starting with FILE_REFERENCE_
): in this case, the file_reference
field of the input location must be refreshed.
The file download operation may return an upload.fileCdnRedirect constructor: in this case, these instructions must be followed for downloading CDN files.
The file download operation may also return one of the following data input errors:
fileHash#6242c773 offset:int limit:int hash:bytes = FileHash;
---functions---
upload.getFileHashes#c7025931 location:InputFileLocation offset:int = Vector<FileHash>;
In order to confirm the integrity of the downloaded file, clients are recommended to verify hashes for each downloaded part, as for CDN DCs.
upload.getFileHashes contain FileHash constructors. Each of these constructors contains the SHA-256 hash of a part of the file that starts with offset
and takes limit
bytes.
Before saving each portion of the data received from the DC into the file, the client can confirm that its hash matches the hash that was received from the master DC. If missing a hash for any file part, client developers must use the upload.getFileHashes method to obtain the missing hash.
Schema:
photoSizeEmpty#e17e23c type:string = PhotoSize;
photoSize#75c78e60 type:string w:int h:int size:int = PhotoSize;
photoCachedSize#21e1ad6 type:string w:int h:int bytes:bytes = PhotoSize;
photoStrippedSize#e0b0bc2e type:string bytes:bytes = PhotoSize;
photoSizeProgressive#fa3efb95 type:string w:int h:int sizes:Vector<int> = PhotoSize;
photoPathSize#d8214d41 type:string bytes:bytes = PhotoSize;
videoSize#de33b094 flags:# type:string w:int h:int size:int video_start_ts:flags.0?double = VideoSize;
document#1e87342b flags:# id:long access_hash:long file_reference:bytes date:int mime_type:string size:int thumbs:flags.0?Vector<PhotoSize> video_thumbs:flags.1?Vector<VideoSize> dc_id:int attributes:Vector<DocumentAttribute> = Document;
photo#fb197a65 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector<PhotoSize> video_sizes:flags.1?Vector<VideoSize> dc_id:int = Photo;
photo#fb197a65 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector<PhotoSize> video_sizes:flags.1?Vector<VideoSize> dc_id:int = Photo;
Telegram attaches a vector of thumbnails with reduced resolution to all uploaded media.
The server also generates a trimmed and scaled down video preview for videos, GIFs and animated profile pictures.
Each photo preview has a specific type
, indicating the resolution and image transform that was applied server-side.
Type | Image filter | Size |
---|---|---|
s |
box | 100x100 |
m |
box | 320x320 |
x |
box | 800x800 |
y |
box | 1280x1280 |
w |
box | 2560x2560 |
a |
crop | 160x160 |
b |
crop | 320x320 |
c |
crop | 640x640 |
d |
crop | 1280x1280 |
Special types:
Type | Image filter |
---|---|
i |
strip |
j |
outline |
photoStrippedSize#e0b0bc2e type:string bytes:bytes = PhotoSize;
A photoStrippedSize (with type i
) is an extremely low-res thumbnail, embedded directly inside media location objects.
It should be shown to the user in chat message previews, or while still downloading the most appropriately sized photoSize through the media DCs as described above.
The stripped bytes
payload should be inflated to a JPG payload as seen here ».
photoPathSize#d8214d41 type:string bytes:bytes = PhotoSize;
Messages with animated stickers can have a compressed svg (< 300 bytes) to show the outline of the sticker before fetching the actual lottie animation.
Animated sticker outlines will have a j
type photoPathSize thumbnail.
This specific vector thumbnail consists in an SVG path, specially encoded to save space.
This path will be the outline of the animated sticker, and should be shown to the user while downloading the actual sticker.
As for stripped sizes, the payload should be inflated using the following algorithm:
encoded := photoPathSize.bytes
lookup := "AACAAAAHAAALMAAAQASTAVAAAZaacaaaahaaalmaaaqastava.az0123456789-,"
path := "M"
len := strlen(encoded)
for (i = 0; i < len; i++) {
num := ord(encoded[i])
if (num >= 128 + 64) {
path += lookup[num - 128 - 64]
} else {
if (num >= 128) {
path += ','
} else if (num >= 64) {
path += '-'
}
path += itoa(num & 63)
}
}
path += "z"
path
will contain the actual SVG path that can be directly inserted in the d
attribute of an svg <path> element:
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512 512" xml:space="preserve">
<path d="{$path}"/>
</svg>
videoSize#de33b094 flags:# type:string w:int h:int size:int video_start_ts:flags.0?double = VideoSize;
A videoSize constructor is typically used for animated profile pictures and video previews.
Type | Description | Format |
---|---|---|
u |
Animated profile picture | MPEG4 |
v |
Video preview | MPEG4 |
Remote HTTP files sent by inline bots in response to inline queries and in other places are represented by WebDocument constructors. When forwarding such remote HTTP files, they should be sent using external InputMedia constructors. Remote HTTP files can only be downloaded directly by the client if contained in a webDocumentNoProxy constructor: in this case, the file is deemed safe to download (this is the case for HTTPS files from certain trusted domains).
However, if the remote file is contained in a webDocument, to avoid leaking sensitive information the file must be downloaded through telegram's servers. This can be done in a manner similar to normal files, with the difference that upload.getWebFile must be used, instead.
upload.webFile#21e753bc size:int mime_type:string file_type:storage.FileType mtime:int bytes:bytes = upload.WebFile;
storage.fileUnknown#aa963b05 = storage.FileType;
storage.fileJpeg#7efe0e = storage.FileType;
storage.fileGif#cae1aadf = storage.FileType;
storage.filePng#a4f63c0 = storage.FileType;
storage.fileMp3#528a0677 = storage.FileType;
storage.fileMov#4b09ebbc = storage.FileType;
storage.filePartial#40bc6f52 = storage.FileType;
storage.fileMp4#b3cea0e4 = storage.FileType;
storage.fileWebp#1081464c = storage.FileType;
---functions---
upload.getWebFile#24e6818d location:InputWebFileLocation offset:int limit:int = upload.WebFile;
The InputWebFileLocation constructor is generated as follows.
inputWebFileLocation#c239d686 url:string access_hash:long = InputWebFileLocation;
inputWebFileGeoPointLocation#9f2221c9 geo_point:InputGeoPoint access_hash:long w:int h:int zoom:int scale:int = InputWebFileLocation;
webDocument#1c570ed1 url:string access_hash:long size:int mime_type:string attributes:Vector<DocumentAttribute> = WebDocument;
inputGeoPoint#48222faf flags:# lat:double long:double accuracy_radius:flags.0?int = InputGeoPoint;
geoPoint#b2a2f663 flags:# long:double lat:double access_hash:long accuracy_radius:flags.0?int = GeoPoint;
url
and access_hash
fields of the webDocument constructor.It is recommended that large queries (upload.getFile, upload.saveFilePart, upload.getWebFile) be handled through a separate session and a separate connection, in which no methods other than these should be executed. If this is done, then data transfer will cause less interference with getting updates and other method calls.
How to handle file references.