Skip to main content
Download files from Osmium servers using the chunked download system.

Download Process

Download File Part

Use media.downloadFilePart to download file data in chunks:
message DownloadFilePart {
  FileRef file_ref = 1;
  uint64 offset = 2;
  uint32 length = 3;
}
file_ref
FileRef
required
Reference to the file to download
offset
uint64
required
Byte offset to start reading from (0-indexed)
length
uint32
required
Number of bytes to read

Response

The server responds with a FilePart message:
message FilePart {
  bytes data = 3;
}
data
bytes
Binary data for the requested file part

FileRef Variants

The FileRef type supports different file reference contexts:
message FileRef {
  oneof ref {
    MediaFileRef media_file = 1;
    ChatPhotoFileRef chat_photo = 2;
  }
}

MediaFileRef

Reference to a file attached to a message:
message MediaFileRef {
  fixed64 file_id = 1;  // @snowflake<File>
}
file_id
fixed64
Snowflake ID of the file

ChatPhotoFileRef

Reference to a chat photo or avatar:
message ChatPhotoFileRef {
  fixed64 file_id = 1;  // @snowflake<File>
}
file_id
fixed64
Snowflake ID of the chat photo

Download Examples

Full File Download

async function downloadFile(fileId, fileSize) {
  const chunkSize = 512 * 1024; // 512 KB
  const chunks = [];
  
  for (let offset = 0; offset < fileSize; offset += chunkSize) {
    const length = Math.min(chunkSize, fileSize - offset);
    
    const response = await client.call('media.downloadFilePart', {
      file_ref: {
        media_file: { file_id: fileId }
      },
      offset: offset,
      length: length
    });
    
    chunks.push(response.data);
  }
  
  return Buffer.concat(chunks);
}

Partial Download (Streaming)

async function* streamFile(fileId, fileSize, chunkSize = 256 * 1024) {
  for (let offset = 0; offset < fileSize; offset += chunkSize) {
    const length = Math.min(chunkSize, fileSize - offset);
    
    const response = await client.call('media.downloadFilePart', {
      file_ref: {
        media_file: { file_id: fileId }
      },
      offset: offset,
      length: length
    });
    
    yield response.data;
  }
}

// Usage
for await (const chunk of streamFile(fileId, fileSize)) {
  // Process chunk (write to disk, display, etc.)
  processChunk(chunk);
}

Download Chat Photo

async function downloadChatPhoto(photoFileId) {
  // Download in one request (assuming small file)
  const response = await client.call('media.downloadFilePart', {
    file_ref: {
      chat_photo: { file_id: photoFileId }
    },
    offset: 0,
    length: 1024 * 1024  // 1 MB max
  });
  
  return response.data;
}

Best Practices

Chunk Size

  • Images/Small files: 256 KB - 512 KB chunks
  • Videos/Large files: 512 KB - 1 MB chunks
  • Streaming: Smaller chunks (128 KB - 256 KB) for faster initial display

Performance

  • Parallel downloads: Download multiple chunks concurrently (with rate limiting)
  • Resume support: Track downloaded offsets to resume interrupted downloads
  • Caching: Cache downloaded files locally to avoid re-downloading

Error Handling

  • Retry logic: Retry failed chunk downloads with exponential backoff
  • Validation: Verify file size matches expected size from metadata
  • Partial data: Handle incomplete chunks gracefully

Download Flow

  1. Get file metadata: Retrieve File object with size and metadata
  2. Calculate chunks: Determine how many chunks needed based on file size
  3. Download parts: Request each part sequentially or in parallel
  4. Reassemble: Concatenate all parts in order
  5. Validate: Verify complete file matches expected size

Build docs developers (and LLMs) love