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 md5_checksum:string = InputFile; inputEncryptedFileUploaded id:long parts:int md5_checksum:string key_fingerprint:int = InputEncryptedFile; inputEncryptedFileBigUploaded id:long parts:int md5_checksum:string 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 file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector<DocumentAttribute> stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia; inputChatUploadedPhoto#94254732 file:InputFile crop:InputPhotoCrop = InputChatPhoto; ---functions--- messages.sendMedia#b8d1262b flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?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> = Updates; messages.sendEncryptedFile peer:InputEncryptedChat random_id:long data:bytes file:InputEncryptedFile = messages.SentEncryptedMessage; photos.uploadProfilePhoto#4f32c098 file:InputFile = photos.Photo; upload.saveFilePart#b304a621 file_id:long file_part:int bytes:bytes = Bool; upload.saveBigFilePart 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:
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:
document#9ba29cc1 flags:# id:long access_hash:long file_reference:bytes date:int mime_type:string size:int thumbs:flags.0?Vector<PhotoSize> 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.
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#e3a6cfb5 location:InputFileLocation offset:int limit:int = upload.File;
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#27d69997 flags:# big:flags.0?true peer:InputPeer volume_id:long local_id:int = InputFileLocation; inputStickerSetThumb#dbaeae9 stickerset:InputStickerSet volume_id:long local_id:int = InputFileLocation; inputStickerSetEmpty#ffb62b95 = InputStickerSet; inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet; inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet; inputPeerSelf#7da07ec9 = InputPeer; inputPeerChat#179be863 chat_id:int = InputPeer; inputPeerUser#7b8e7de6 user_id:int access_hash:long = InputPeer; inputPeerChannel#20adaef8 channel_id:int access_hash:long = InputPeer; photo#d07504a5 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector<PhotoSize> dc_id:int = Photo; document#9ba29cc1 flags:# id:long access_hash:long file_reference:bytes date:int mime_type:string size:int thumbs:flags.0?Vector<PhotoSize> dc_id:int attributes:Vector<DocumentAttribute> = Document; photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize; photoCachedSize#e9a734fa type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize;
For photos, inputPhotoFileLocation is used:
For profile pictures of users, channels, supergroups and groups, since in most occasions they are encountered as simple fileLocationToBeDeprecated constructors without an associated photo, inputPeerPhotoFileLocation has to be used:
peeris the identifier of the peer whose photo we want to download
local_idare extracted from the fileLocationToBeDeprecated of the desired quality (the logic for selecting the quality of profile pictures will be changed soon)
For documents, inputDocumentFileLocation is used:
For 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 previews of sticker sets, inputStickerSetThumb is used (note: to download stickers and previews of stickers use the document method described above):
For old deprecated photos, if the client has cached some old fileLocations with the deprecated
secret identifier, inputFileLocation is used (this is mainly used for backwards compatiblity with bot API file IDs, all user clients must use the modern inputPhotoFileLocation file IDs):
access_hashtaken from the photo constructor
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, also:
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
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.
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#f3b7acc9 lat:double long:double = InputGeoPoint; geoPoint#296f104 long:double lat:double access_hash:long = GeoPoint;
access_hashfields of the webDocument constructor.
It is recommended that large queries (upload.getFile, upload.saveFilePart) 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.