SiaSia Developer Portal

Download an Object

Once your application has uploaded an object to Sia, downloading is straightforward. The SDK handles all network coordination: locating slabs, downloading encrypted shards, verifying them, and decrypting your data locally.

Downloads stream decrypted bytes into a writable destination. Depending on the SDK, that destination might be a custom Writer, an in-memory buffer, or a file handle. This makes it easy to download small objects into memory or stream large objects directly to disk.

Prerequisites

Before proceeding, ensure you have:

  • An App Key returned from a successful connection to an indexer.
  • An Object ID from an object pinned to your account.

Once ready, you can download the object into memory, into a file, or into another writable destination supported by your SDK.

Example

rust
use sia_storage::{app_id, AppKey, AppMetadata, Builder, DownloadOptions, Hash256}; use std::io::{self, Write}; use std::str::FromStr; use tokio::io::AsyncReadExt; const INDEXER_URL: &str = "https://sia.storage"; const APP_META: AppMetadata = AppMetadata { // Replace `app_id` with your real 32-byte App ID (hex-encoded, 64 chars). // Generate this ONCE and keep it stable forever for your app. id: app_id!("0000000000000000000000000000000000000000000000000000000000000000"), name: "My App", description: "Demo application", service_url: "https://example.com", logo_url: None, callback_url: None, }; #[tokio::main(flavor = "multi_thread")] async fn main() -> Result<(), Box<dyn std::error::Error>> { // Create a builder that can reconnect using an existing App Key let builder = Builder::new(INDEXER_URL, APP_META)?; // Ask the user for their App Key print!("Enter your App Key (hex): "); io::stdout().flush()?; let mut app_key_hex = String::new(); io::stdin().read_line(&mut app_key_hex)?; let app_key_hex = app_key_hex.trim(); let mut seed = [0u8; 32]; hex::decode_to_slice(app_key_hex, &mut seed)?; let app_key = AppKey::import(seed); // Reconnect using the App Key let sdk = match builder.connected(&app_key).await? { Some(sdk) => sdk, None => { return Err(io::Error::new( io::ErrorKind::PermissionDenied, "invalid App Key", ) .into()) } }; println!("\nApp Connected!"); // Ask the user for the Object ID to download print!("Enter the Object ID to download: "); io::stdout().flush()?; let mut object_id = String::new(); io::stdin().read_line(&mut object_id)?; let object_id = Hash256::from_str(object_id.trim())?; // Look up the object from the indexer let obj = sdk.object(&object_id).await?; // Use an in-memory duplex stream so we can download into memory // without writing a temporary file to disk. let (mut writer, mut reader) = tokio::io::duplex(64 * 1024); let download_fut = async { sdk.download(&mut writer, &obj, DownloadOptions::default()) .await?; drop(writer); Ok::<(), Box<dyn std::error::Error>>(()) }; let read_fut = async { let mut bytes = Vec::new(); reader.read_to_end(&mut bytes).await?; Ok::<Vec<u8>, Box<dyn std::error::Error>>(bytes) }; let (_, bytes) = tokio::try_join!(download_fut, read_fut)?; println!("\nObject downloaded!"); println!(" - Contents: {}", String::from_utf8_lossy(&bytes)); Ok(()) }