curlcloud-storagepcloud

Download files with the pCloud API


I am trying to make friends with the pCloud API, using curl in Bash,

Once I create a pCloud app and get its $clientid and $clientsecret, I can obtain a temporary access token accepting the request at:

echo "https://my.pcloud.com/oauth2/authorize?client_id=$clientid&response_type=code"

And given the $temptok token, I obtain the permanent bearer token with:

permtok=$(curl "https://api.pcloud.com/oauth2_token?client_id=$clientid&client_secret=$clientsecret&code=$temptok" | jq -r '.access_token')

At this point, I can use their API methods, published here.
For example, the userinfo or the listfolder method, which give:

curl "https://api.pcloud.com/userinfo?access_token=$permtok"
curl "https://api.pcloud.com/listfolder?access_token=$permtok&path=/"   

However, I am unable to download files. Based on my understanding, I need to use a combination of file_open and file_read, and the latter needs the file size. When I open a file, I get an output similar to what follows:

curl "https://api.pcloud.com/file_open?access_token=$permtok&path=/foo.txt&flags=0x0040"                      
{
    "result": 0,
    "fd": 1,
    "fileid": 1234567890
}

When using the file descriptor for file_size method:

curl "https://api.pcloud.com/file_size?access_token=$permtok&fd=1"

I get the error:

{
    "result": 1007,
    "error": "Invalid or closed file descriptor."
}

What is the correct way to download files?


Solution

  • The solution proposed by @Bench Vue creates a public link for the file to download. So it is not suitable for private files. Also, once you have a public download link, leveraging the API, with the related authentication steps, might be overkilling.

    Here is the solution for private files, which should not be publicly shared.

    Obtain your permanent bearer oauth2 as described here, which is permanent.

    # Input pars
    permtok="....."
    source="/foo bar.pdf"
    dest="foo bar.pdf"
    endpoint="https://api.pcloud.com"
     
    # Encode source path
    encsource=$(printf %s "$source" |jq -sRr @uri)
     
    # Get file size 
    size=$(curl -H "Connection: keep-alive" \
           "$endpoint/file_open?access_token=$permtok&path=$encsource&flags=64" \
           "$endpoint/file_size?access_token=$permtok&fd=1" \
           | jq -s '.[1] | .size')
     
    # Download
    curl -H "Connection: keep-alive" \
           "$endpoint/file_open?access_token=$permtok&path=$encsource&flags=64" \
           "$endpoint/file_read?access_token=$permtok&fd=1&count=$size" > "$dest"
           
    

    Use listfolder method to find the correct source path, which might be relative to your application folder.

    curl "$endpoint/listfolder?access_token=$permtok&path=/"   
    

    $endpoint can change depending on your region.

    The API server is HTTP 1.1, therefore "Connection: keep-alive" is necessary.