Rust
Rust
Facebook Download all Photos to Local Files
See more Facebook Examples
Demonstrates how to download all of one's Facebook photos to a local filesystem directory. This sample code keeps a local cache to avoid re-downloading the same photos twice. The program can be run again after a time, and it will download only photos that haven't yet been downloaded.Chilkat Rust Downloads
// This example requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
// This example will use a local disk cache to avoid re-fetching the same
// photo id after it's been fetched once.
let fb_cache = chilkat::Cache::new();
// The cache will use 1 level of 256 sub-directories.
fb_cache.set_level(1);
// Use a directory path that makes sense on your operating system..
fb_cache.add_root("C:/fbCache");
// This example assumes a previously obtained an access token
let oauth2 = chilkat::OAuth2::new();
oauth2.set_access_token("FACEBOOK-ACCESS-TOKEN");
let rest = chilkat::Rest::new();
// Connect to Facebook.
if rest.connect("graph.facebook.com", 443, true, true).is_err() {
println!("{}", rest.last_error_text());
return;
}
// Provide the authentication credentials (i.e. the access key)
let _ = rest.set_auth_o_auth2(&oauth2);
// There are two choices:
// We can choose to download the photos the person is tagged in or has uploaded
// by setting type to "tagged" or "uploaded".
let _ = rest.add_query_param("type", "uploaded");
// To download all photos, we begin with an outer loop that iterates over
// the list of photo nodes in pages. Each page returned contains a list of
// photo node ids. Each photo node id must be retrieved to get the download URL(s)
// of the actual image.
// I don't know the max limit for the number of records that can be downloaded at once.
let _ = rest.add_query_param("limit", "100");
// Get the 1st page of photos ids.
// See https://developers.facebook.com/docs/graph-api/reference/user/photos/ for more information.
let Ok(mut response_json) = rest.full_request_no_body("GET", "/v2.7/me/photos") else {
println!("{}", rest.last_error_text());
return;
};
let photo_json = chilkat::JsonObject::new();
let sa_photo_urls = chilkat::StringArray::new();
let sb_photo_id_path = chilkat::StringBuilder::new();
let json = chilkat::JsonObject::new();
json.set_emit_compact(false);
let _ = json.load(&response_json);
let mut i: i32 = 0;
let mut photo_id = String::new();
let mut image_url = String::new();
// Get the "after" cursor.
let mut after_cursor = json.string_of("paging.cursors.after").unwrap_or_default();
while json.last_method_success() {
println!("-------------------");
println!("afterCursor = {}", after_cursor);
// For each photo id in this page...
i = 0;
let num_items = json.size_of_array("data");
while i < num_items {
json.set_i(i);
photo_id = json.string_of("data[i].id").unwrap_or_default();
println!("photoId = {}", photo_id);
// We need to fetch the JSON for this photo. Check to see if it's in the local disk cache,
// and if not, then get it from Facebook.
let mut photo_json_str = fb_cache.fetch_text(&photo_id).unwrap_or_default();
if !fb_cache.last_method_success() {
// It's not locally available, so get it from Facebook..
sb_photo_id_path.clear();
let _ = sb_photo_id_path.append("/v2.7/");
let _ = sb_photo_id_path.append(&photo_id);
let _ = rest.clear_all_query_params();
let _ = rest.add_query_param("fields", "id,album,images");
println!("Fetching photo node from Facebook...");
// This REST request will continue using the existing connection.
// If the connection was closed, it will automatically reconnect to send the request.
photo_json_str = rest.full_request_no_body("GET", &sb_photo_id_path.get_as_string().unwrap_or_default()).unwrap_or_default();
if !rest.last_method_success() {
println!("{}", rest.last_error_text());
return;
}
// Add the photo JSON to the local cache.
let _ = fb_cache.save_text_no_expire(&photo_id, "", &photo_json_str);
}
// Parse the photo JSON and add the main photo download URL to saPhotoUrls
// There may be multiple URLs in the images array, but the 1st one is the largest and main photo URL.
// The others are smaller sizes of the same photo.
let _ = photo_json.load(&photo_json_str);
image_url = photo_json.string_of("images[0].source").unwrap_or_default();
if photo_json.last_method_success() {
// Actually, we'll add a small JSON document that contains both the image ID and the URL.
let img_url_json = chilkat::JsonObject::new();
let _ = img_url_json.append_string("id", &photo_id);
let _ = img_url_json.append_string("url", &image_url);
let _ = sa_photo_urls.append(&img_url_json.emit().unwrap_or_default());
println!("imageUrl = {}", image_url);
}
i = i + 1;
}
// Prepare for getting the next page of photos ids.
// We can continue using the same REST object.
// If already connected, we'll continue using the existing connection.
// Otherwise, a new connection will automatically be made if needed.
let _ = rest.clear_all_query_params();
let _ = rest.add_query_param("type", "uploaded");
let _ = rest.add_query_param("limit", "20");
let _ = rest.add_query_param("after", &after_cursor);
// Get the next page of photo ids.
response_json = rest.full_request_no_body("GET", "/v2.7/me/photos").unwrap_or_default();
if !rest.last_method_success() {
println!("{}", rest.last_error_text());
return;
}
let _ = json.load(&response_json);
after_cursor = json.string_of("paging.cursors.after").unwrap_or_default();
}
println!("No more pages of photos.");
// Now iterate over the photo URLs and download each to a file.
// We can use Chilkat HTTP. No Facebook authorization (access token) is required to download
// the photo once the URL is known.
let http = chilkat::Http::new();
// We'll cache the image data so that if run again, we don't re-download the same image again.
let num_urls = sa_photo_urls.count();
i = 0;
let url_json = chilkat::JsonObject::new();
let fac = chilkat::FileAccess::new();
while i < num_urls {
let _ = url_json.load(&sa_photo_urls.get_string(i).unwrap_or_default());
photo_id = url_json.string_of("id").unwrap_or_default();
image_url = url_json.string_of("url").unwrap_or_default();
// Check the local cache for the image data.
// Only download and save if not already cached.
image_bytes = fb_cache.fetch_from_cache(&image_url);
if !fb_cache.last_method_success() {
// This photo needs to be downloaded.
let sb_image_url = chilkat::StringBuilder::new();
let _ = sb_image_url.append(&image_url);
// Let's form a filename..
let mut extension = ".jpg".to_string();
if sb_image_url.contains(".gif", false) {
extension = ".gif".to_string();
}
if sb_image_url.contains(".png", false) {
extension = ".png".to_string();
}
if sb_image_url.contains(".tiff", false) {
extension = ".tiff".to_string();
}
if sb_image_url.contains(".bmp", false) {
extension = ".bmp".to_string();
}
let sb_local_file_path = chilkat::StringBuilder::new();
let _ = sb_local_file_path.append("C:/Photos/facebook/uploaded/");
let _ = sb_local_file_path.append(&photo_id);
let _ = sb_local_file_path.append(&extension);
image_bytes = http.quick_get(&image_url);
if !http.last_method_success() {
println!("{}", http.last_error_text());
return;
}
// We've downloaded the photo image bytes into memory.
// Save it to the cache AND save it to the output file.
let _ = fb_cache.save_to_cache_no_expire(&image_url, "", &image_bytes);
let _ = fac.write_entire_file(&sb_local_file_path.get_as_string().unwrap_or_default(), &image_bytes);
println!("Downloaded to {}", sb_local_file_path.get_as_string().unwrap_or_default());
}
i = i + 1;
}
println!("Finished downloading all Facebook photos!");