Sample code for 30+ languages & platforms
Lua

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 Lua Downloads

Lua
local chilkat = require("chilkat")

-- 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.
local fbCache = chilkat.Cache.new()
-- The cache will use 1 level of 256 sub-directories.
fbCache.level = 1
-- Use a directory path that makes sense on your operating system..
fbCache:add_root("C:/fbCache")

-- This example assumes a previously obtained an access token
local oauth2 = chilkat.OAuth2.new()
oauth2.access_token = "FACEBOOK-ACCESS-TOKEN"

local rest = chilkat.Rest.new()

-- Connect to Facebook.
local success = rest:connect("graph.facebook.com", 443, true, true)
if not success then
    print(rest.last_error_text)
    return
end

-- Provide the authentication credentials (i.e. the access key)
rest:set_auth_oauth2(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".
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.
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.
local responseJson = rest:full_request_no_body("GET", "/v2.7/me/photos")
if not rest.last_method_success then
    print(rest.last_error_text)
    return
end

local photoJson = chilkat.JsonObject.new()
local saPhotoUrls = chilkat.StringArray.new()
local sbPhotoIdPath = chilkat.StringBuilder.new()

local json = chilkat.JsonObject.new()
json.emit_compact = false
json:load(responseJson)

local i = 0
local photoId = ""
local imageUrl = ""

-- Get the "after" cursor.
local afterCursor = json:string_of("paging.cursors.after")
while json.last_method_success do
    print("-------------------")
    print("afterCursor = " .. afterCursor)

    -- For each photo id in this page...
    i = 0
    local numItems = json:size_of_array("data")
    while i < numItems do
        json.i = i
        photoId = json:string_of("data[i].id")
        print("photoId = " .. photoId)

        -- 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.
        local photoJsonStr = fbCache:fetch_text(photoId)
        if not fbCache.last_method_success then
            -- It's not locally available, so get it from Facebook..
            sbPhotoIdPath:clear()
            sbPhotoIdPath:append("/v2.7/")
            sbPhotoIdPath:append(photoId)

            rest:clear_all_query_params()
            rest:add_query_param("fields", "id,album,images")

            print("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.
            photoJsonStr = rest:full_request_no_body("GET", sbPhotoIdPath:get_as_string())
            if not rest.last_method_success then
                print(rest.last_error_text)
                return
            end

            -- Add the photo JSON to the local cache.
            fbCache:save_text_no_expire(photoId, "", photoJsonStr)
        end

        -- 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.
        photoJson:load(photoJsonStr)
        imageUrl = photoJson:string_of("images[0].source")
        if photoJson.last_method_success then
            -- Actually, we'll add a small JSON document that contains both the image ID and the URL.
            local imgUrlJson = chilkat.JsonObject.new()
            imgUrlJson:append_string("id", photoId)
            imgUrlJson:append_string("url", imageUrl)
            saPhotoUrls:append(imgUrlJson:emit())
            print("imageUrl = " .. imageUrl)
        end

        i = i + 1
    end

    -- 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.
    rest:clear_all_query_params()
    rest:add_query_param("type", "uploaded")
    rest:add_query_param("limit", "20")
    rest:add_query_param("after", afterCursor)

    -- Get the next page of photo ids.
    responseJson = rest:full_request_no_body("GET", "/v2.7/me/photos")
    if not rest.last_method_success then
        print(rest.last_error_text)
        return
    end

    json:load(responseJson)
    afterCursor = json:string_of("paging.cursors.after")
end

print("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.
local http = chilkat.Http.new()

-- We'll cache the image data so that if run again, we don't re-download the same image again.
local numUrls = saPhotoUrls.count
i = 0
local urlJson = chilkat.JsonObject.new()

local fac = chilkat.FileAccess.new()

while i < numUrls do
    urlJson:load(saPhotoUrls:get_string(i))
    photoId = urlJson:string_of("id")
    imageUrl = urlJson:string_of("url")

    -- Check the local cache for the image data.
    -- Only download and save if not already cached.
    imageBytes = ERROR: Method not in Chilkat for Lua: Cache.FetchFromCache
fbCache:ERROR()
    if not fbCache.last_method_success then
        --  This photo needs to be downloaded.

        local sbImageUrl = chilkat.StringBuilder.new()
        sbImageUrl:append(imageUrl)

        -- Let's form a filename..
        local extension = ".jpg"
        if sbImageUrl:contains(".gif", false) then
            extension = ".gif"
        end

        if sbImageUrl:contains(".png", false) then
            extension = ".png"
        end

        if sbImageUrl:contains(".tiff", false) then
            extension = ".tiff"
        end

        if sbImageUrl:contains(".bmp", false) then
            extension = ".bmp"
        end

        local sbLocalFilePath = chilkat.StringBuilder.new()
        sbLocalFilePath:append("C:/Photos/facebook/uploaded/")
        sbLocalFilePath:append(photoId)
        sbLocalFilePath:append(extension)

        imageBytes = ERROR: Method not in Chilkat for Lua: Http.QuickGet
http:ERROR()
        if not http.last_method_success then
            print(http.last_error_text)
            return
        end

        -- We've downloaded the photo image bytes into memory.
        -- Save it to the cache AND save it to the output file.
ERROR: Method not in Chilkat for Lua: Cache.SaveToCacheNoExpire
        fbCache:ERROR()
ERROR: Method not in Chilkat for Lua: FileAccess.WriteEntireFile
        fac:ERROR()

        print("Downloaded to " .. sbLocalFilePath:get_as_string())
    end

    i = i + 1
end

print("Finished downloading all Facebook photos!")