Sample code for 30+ languages & platforms
Xbase++

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 Xbase++ Downloads

Xbase++
LOCAL nSuccess
LOCAL oFbCache
LOCAL oOauth2
LOCAL oRest
LOCAL cResponseJson
LOCAL oPhotoJson
LOCAL oSaPhotoUrls
LOCAL oSbPhotoIdPath
LOCAL oJson
LOCAL i
LOCAL cPhotoId
LOCAL cImageUrl
LOCAL cAfterCursor
LOCAL nNumItems
LOCAL cPhotoJsonStr
LOCAL oImgUrlJson
LOCAL oHttp
LOCAL nNumUrls
LOCAL oUrlJson
LOCAL oFac
LOCAL oSbImageUrl
LOCAL cExtension
LOCAL oSbLocalFilePath

nSuccess := 0

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

//  This example assumes a previously obtained an access token
oOauth2 := CreateObject("Chilkat.OAuth2")
oOauth2:AccessToken := "FACEBOOK-ACCESS-TOKEN"

oRest := CreateObject("Chilkat.Rest")

//  Connect to Facebook.
nSuccess := oRest:Connect("graph.facebook.com", 443, 1, 1)
IF (nSuccess != 1)
    ? oRest:LastErrorText
    oFbCache:destroy()
    oOauth2:destroy()
    oRest:destroy()
    RETURN
ENDIF

//  Provide the authentication credentials (i.e. the access key)
oRest:SetAuthOAuth2(oOauth2)

//  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".
oRest:AddQueryParam("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.
oRest:AddQueryParam("limit", "100")

//  Get the 1st page of photos ids.
//  See https://developers.facebook.com/docs/graph-api/reference/user/photos/ for more information.
cResponseJson := oRest:FullRequestNoBody("GET", "/v2.7/me/photos")
IF (oRest:LastMethodSuccess != 1)
    ? oRest:LastErrorText
    oFbCache:destroy()
    oOauth2:destroy()
    oRest:destroy()
    RETURN
ENDIF

oPhotoJson := CreateObject("Chilkat.JsonObject")
oSaPhotoUrls := CreateObject("Chilkat.StringArray")
oSbPhotoIdPath := CreateObject("Chilkat.StringBuilder")

oJson := CreateObject("Chilkat.JsonObject")
oJson:EmitCompact := 0
oJson:Load(cResponseJson)

//  Get the "after" cursor.
cAfterCursor := oJson:StringOf("paging.cursors.after")
DO WHILE oJson:LastMethodSuccess == 1

    ? "-------------------"
    ? "afterCursor = " + cAfterCursor

    //  For each photo id in this page...
    i := 0
    nNumItems := oJson:SizeOfArray("data")
    DO WHILE i < nNumItems
        oJson:I := i
        cPhotoId := oJson:StringOf("data[i].id")
        ? "photoId = " + cPhotoId

        //  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.
        cPhotoJsonStr := oFbCache:FetchText(cPhotoId)
        IF (oFbCache:LastMethodSuccess == 0)
            //  It's not locally available, so get it from Facebook..
            oSbPhotoIdPath:Clear()
            oSbPhotoIdPath:Append("/v2.7/")
            oSbPhotoIdPath:Append(cPhotoId)

            oRest:ClearAllQueryParams()
            oRest:AddQueryParam("fields", "id,album,images")

            ? "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.
            cPhotoJsonStr := oRest:FullRequestNoBody("GET", oSbPhotoIdPath:GetAsString())
            IF (oRest:LastMethodSuccess != 1)
                ? oRest:LastErrorText
                oFbCache:destroy()
                oOauth2:destroy()
                oRest:destroy()
                oPhotoJson:destroy()
                oSaPhotoUrls:destroy()
                oSbPhotoIdPath:destroy()
                oJson:destroy()
                RETURN
            ENDIF

            //  Add the photo JSON to the local cache.
            oFbCache:SaveTextNoExpire(cPhotoId, "", cPhotoJsonStr)
        ENDIF

        //  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.
        oPhotoJson:Load(cPhotoJsonStr)
        cImageUrl := oPhotoJson:StringOf("images[0].source")
        IF (oPhotoJson:LastMethodSuccess == 1)

            //  Actually, we'll add a small JSON document that contains both the image ID and the URL.
            oImgUrlJson := CreateObject("Chilkat.JsonObject")
            oImgUrlJson:AppendString("id", cPhotoId)
            oImgUrlJson:AppendString("url", cImageUrl)
            oSaPhotoUrls:Append(oImgUrlJson:Emit())
            ? "imageUrl = " + cImageUrl
        ENDIF

        i := i + 1
    ENDDO

    //  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.
    oRest:ClearAllQueryParams()
    oRest:AddQueryParam("type", "uploaded")
    oRest:AddQueryParam("limit", "20")
    oRest:AddQueryParam("after", cAfterCursor)

    //  Get the next page of photo ids.
    cResponseJson := oRest:FullRequestNoBody("GET", "/v2.7/me/photos")
    IF (oRest:LastMethodSuccess != 1)
        ? oRest:LastErrorText
        oFbCache:destroy()
        oOauth2:destroy()
        oRest:destroy()
        oPhotoJson:destroy()
        oSaPhotoUrls:destroy()
        oSbPhotoIdPath:destroy()
        oJson:destroy()
        oImgUrlJson:destroy()
        RETURN
    ENDIF

    oJson:Load(cResponseJson)
    cAfterCursor := oJson:StringOf("paging.cursors.after")
ENDDO

? "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.  
oHttp := CreateObject("Chilkat.Http")

//  We'll cache the image data so that if run again, we don't re-download the same image again.
nNumUrls := oSaPhotoUrls:Count
i := 0
oUrlJson := CreateObject("Chilkat.JsonObject")

oFac := CreateObject("Chilkat.FileAccess")

DO WHILE i < nNumUrls
    oUrlJson:Load(oSaPhotoUrls:GetString(i))
    cPhotoId := oUrlJson:StringOf("id")
    cImageUrl := oUrlJson:StringOf("url")

    //  Check the local cache for the image data.
    //  Only download and save if not already cached.
    oImageBytes := oFbCache:FetchFromCache(cImageUrl)
    IF (oFbCache:LastMethodSuccess == 0)
        //   This photo needs to be downloaded.

        oSbImageUrl := CreateObject("Chilkat.StringBuilder")
        oSbImageUrl:Append(cImageUrl)

        //  Let's form a filename..
        cExtension := ".jpg"
        IF (oSbImageUrl:Contains(".gif", 0) == 1)
            cExtension := ".gif"
        ENDIF

        IF (oSbImageUrl:Contains(".png", 0) == 1)
            cExtension := ".png"
        ENDIF

        IF (oSbImageUrl:Contains(".tiff", 0) == 1)
            cExtension := ".tiff"
        ENDIF

        IF (oSbImageUrl:Contains(".bmp", 0) == 1)
            cExtension := ".bmp"
        ENDIF

        oSbLocalFilePath := CreateObject("Chilkat.StringBuilder")
        oSbLocalFilePath:Append("C:/Photos/facebook/uploaded/")
        oSbLocalFilePath:Append(cPhotoId)
        oSbLocalFilePath:Append(cExtension)

        oImageBytes := oHttp:QuickGet(cImageUrl)
        IF (oHttp:LastMethodSuccess != 1)
            ? oHttp:LastErrorText
            oFbCache:destroy()
            oOauth2:destroy()
            oRest:destroy()
            oPhotoJson:destroy()
            oSaPhotoUrls:destroy()
            oSbPhotoIdPath:destroy()
            oJson:destroy()
            oImgUrlJson:destroy()
            oHttp:destroy()
            oUrlJson:destroy()
            oFac:destroy()
            oSbImageUrl:destroy()
            oSbLocalFilePath:destroy()
            RETURN
        ENDIF

        //  We've downloaded the photo image bytes into memory.
        //  Save it to the cache AND save it to the output file.
        oFbCache:SaveToCacheNoExpire(cImageUrl, "", oImageBytes)
        oFac:WriteEntireFile(oSbLocalFilePath:GetAsString(), oImageBytes)

        ? "Downloaded to " + oSbLocalFilePath:GetAsString()
    ENDIF

    i := i + 1
ENDDO

? "Finished downloading all Facebook photos!"

oFbCache:destroy()
oOauth2:destroy()
oRest:destroy()
oPhotoJson:destroy()
oSaPhotoUrls:destroy()
oSbPhotoIdPath:destroy()
oJson:destroy()
oImgUrlJson:destroy()
oHttp:destroy()
oUrlJson:destroy()
oFac:destroy()
oSbImageUrl:destroy()
oSbLocalFilePath:destroy()