Using PHP to upload an activity to Strava using API v3 - php

I'm working on an application in which I'd like to be able to upload activities (GPX files) to Strava using it's API v3.
My application successfully handles the OAuth process - I'm able to request activities, etc, successfully.
However, when I try to upload an activity - it fails.
Here's the relevant sample of my code:
// $filename is the name of the GPX file
// $actual_file contains the full path
$actual_file = realpath($filename);
$url="https://www.strava.com/api/v3/uploads";
$postdata = "activity_type=ride&file=". "#" . $actual_file . ";filename=" . $filename . "&data_type=gpx";
$headers = array('Authorization: Bearer ' . $strava_access_token);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
curl_setopt($ch, CURLOPT_POST, 3);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec ($ch);
Here's what I get in response:
{"message":"Bad Request", "errors":[{"resource":"Upload", "field":"file","code":"not a file"}]}
I then tried this:
// $filename is the name of the GPX file
// $actual_file contains the full path
$actual_file = realpath($filename);
$url="https://www.strava.com/api/v3/uploads";
$postfields = array(
"activity_type" => "ride",
"data_type" => "gpx",
"file" => "#" . $filename
);
$postdata = http_build_query($postfields);
$headers = array('Authorization: Bearer ' . $strava_access_token, "Content-Type: application/octet-stream");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
curl_setopt($ch, CURLOPT_POST, count($postfields));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$fp = fopen($filename, 'r');
curl_setopt($ch, CURLOPT_INFILE, $fp);
$json = curl_exec ($ch);
$error = curl_error ($ch);
Here's what I get in response:
{"message":"Bad Request", "errors":[{"resource":"Upload", "field":"data","code":"empty"}]}
Clearly, I'm doing something wrong when trying to pass the GPX file.
Is it possible to provide a bit of sample PHP code to show how this should work?
For what it's worth - I'm fairly certain the GPX file is valid (it's actually a file I downloaded using Strava's export feature).

I hope that answering my own question less than one day after posting it isn't bad form. But I've got it working, so I may as well, just in case anyone else finds it useful...
// $filename is the name of the file
// $actual_file includes the filename and the full path to the file
// $strava_access_token contains the access token
$actual_file = realpath($filename);
$url="https://www.strava.com/api/v3/uploads";
$postfields = array(
"activity_type" => "ride",
"data_type" => "gpx",
"file" => '#' . $actual_file . ";type=application/xml"
);
$headers = array('Authorization: Bearer ' . $strava_access_token);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec ($ch);
Apparently, it's important not to include the CURLOPT_POST option.

Here is also a working Python example
import os
import requests
headers = {
'accept': 'application/json',
'authorization': 'Bearer <Token>',
}
dir = os.getcwd() + '/files/'
for filename in os.listdir(dir):
file = open(dir + filename, 'rb')
files = {
"file": (filename, file, 'application/gpx+xml'),
"data_type": (None, 'gpx'),
}
try:
response = requests.post('http://www.strava.com/api/v3/uploads',files=files, headers=headers)
print(filename)
print(response.text)
print(response.headers)
except requests.exceptions.RequestException as e: # This is the correct syntax
print(e)
sys.exit(1)

Related

DROPBOX API Not uploading more than 150MB File

Hi Please first read full question then answer.
I am trying to upload the files using Dropbox API But now I came to know that I cannot upload more than 150MB file with that method.
Here are my Codes.
<?php
define ('SITE_ROOT', realpath(dirname(__FILE__)));
$filename = SITE_ROOT.'BRINDABELLA.zip';
$MainPath = '/2020 events/';
$api_url = 'https://content.dropboxapi.com/2/files/upload';
$token = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
$headers = array('Authorization: Bearer '. $token,
'Content-Type: application/octet-stream',
'Dropbox-API-Arg: '.
json_encode(
array(
"path"=> $MainPath.basename($filename),
"mode" => "add",
"autorename" => true,
"mute" => false
)
)
);
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, true);
$path = $filename;
$fp = fopen($path, 'rb');
$filesize = filesize($path);
curl_setopt($ch, CURLOPT_POSTFIELDS, fread($fp, $filesize));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_VERBOSE, 1); // debug
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
echo($response.'<br/>');
echo($http_code.'<br/>');
curl_close($ch);
?>
I Know I can upload more than 150MB files using upload session method.
Reference Link https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-start
Now I just want to alter my these codes only. Please help me how I can do it. I dont want to use any external API. Just the way I used CURL

Sending an voice file to API (laravel) - 5.4

I am trying to send a voice file to my api built in laravel. Everything seems right in my code but when i send the file to my api, i check at my api side if the data posted has file contained in it but i keep getting false. Am i posting my voice file wrongly.
Path: Absolute path
PHP version : 7.0
$endPoint = 'https://api.domain.com/api';
$apiKey = '**********';
$url = $endPoint . '?key=' . $apiKey;
$curlFile = new \CurlFile('/Users/public/Voice/aaaah.wav');
$data = [
'message' => 'First Voice',
'file' => $curlFile,
];
$ch = curl_init();
$headers = array();
$headers[] = "Content-Type: multipart/form-data";
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
$result = curl_exec($ch);
$result = json_decode($result, TRUE);
curl_close($ch);
return $result;

Strava V3 api upload gpx file php

i'm trying to upload a gpx file using strava api. I've already got the access token and i'm using this script :
$actual_file= realpath('/.../../myfile.gpx');
$url="https://www.strava.com/api/v3/uploads";
$postfields = array(
"activity_type" => "ride",
"data_type" => "gpx",
"file" => '#' . $actual_file . ";type=application/xml"
);
$headers = array('Authorization: Bearer ' . $token);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec ($ch);
echo $response;
but the response i get from strava is {"message":"Bad Request","errors":[{"resource":"Upload","field":"file","code":"not a file"}]}
I found out that you should use "file" => curl_file_create($actual_file) for the file param. Also those params are out of date (check out the new doc).
I hope this will help someone. I discovered it while look through this PHP wrapper for Strava's API

Upload item image using Square Connect API and PHP

I've reviewed the old questions posted here on Stackoverflow about this issue.
But I didn't find any example for php integration.
Here is a sample of my code to do that but it's failing
$url = 'https://connect.squareup.com/v1/me/items/9999999/image';
$auth_bearer = 'Authorization: Bearer ' . $this->accessToken;
$image_data = base64_encode(file_get_contents('image.jpeg'));
$header = array(
$auth_bearer,
'Accept: application/json',
'Content-Type: multipart/form-data; boundary=BOUNDARY',
);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'files=' . $image_data);
$head = curl_exec($ch);
curl_close($ch);
$response = json_decode($head);
echo "<pre>";
print_r($response);
echo "</pre>";
And nothing happens... any help here?
Thanks
You need to post the raw image data (not base64 encoded) with the proper multipart header for a file object. Here's a working example (replace ACCESS_TOKEN, ITEM_ID, and IMAGE_FILE).
<?php
function uploadItemImage($url, $access_token, $image_file) {
$headers = ["Authorization: Bearer $access_token"];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, ['image_data' => "#$image_file"]);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
$return_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
print "POST to $url with status $return_status\n";
curl_close($ch);
return $data ? json_decode($data) : false;
}
print_r(
uploadItemImage(
'https://connect.squareup.com/v1/me/items/ITEM_ID/image',
'ACCESS_TOKEN',
'IMAGE_FILE.jpg'
)
);
?>
Here is my PHP implementation for uploading a PNG image. Sometimes a different code view helps.
As #Troy stated, the important field to include for images is 'Content-Type: multipart/form-data'. Everything else I upload to Square uses 'Content-Type: application/json'.
$square_url = 'https://connect.squareup.com/v1/me/items/' . $square_item_id . '/image';
$cfile = new CURLFile($image_path_on_server, 'image/png', 'image_data');
$image_data = array('image_data' => $cfile);
$curl = curl_init();
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Authorization: Bearer ' . $access_token,
'Content-Type: multipart/form-data',
'Accept: application/json'
));
curl_setopt($curl, CURLOPT_POSTFIELDS, $image_data);
curl_setopt($curl, CURLOPT_URL, $square_url);
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_SAFE_UPLOAD, TRUE);
curl_setopt($curl, CURLOPT_BINARYTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($curl, CURLINFO_HEADER_OUT, TRUE);
curl_setopt($curl, CURLOPT_VERBOSE, TRUE);
$json = curl_exec($curl);
curl_close($curl);
Strictly speaking Square API documentation, their method can be implemented keeping a few things in mind.
-- Your request must be enclosed in a boundary and contain the Content disposition, name, filename, content type like the sample below.
--BOUNDARY
Content-Disposition: form-data; name="image_data"; filename="MyImage.png"
Content-Type: image/png
{BLANK LINE IS REQUIRED}
IMAGE BINARY DATA GOES HERE
--BOUNDARY--
In essence, the format of the request must be exactly as specified in the sample. This includes the 'boundary', the newline characters, the necessary headers, a blank line between the headers (for some reason nothing works if the line isn't present), and the actual image binary data. NOTE: the boundary can be any string that you choose, but it must be used consistently. In code, this would look something like this:
$boundary = "---------------------" . md5(mt_rand() . microtime());
$imageToUpload = "--{$boundary}" . "\r\n" .
"Content-Disposition: form-data; name=\"image_data\"; filename=\"" . $full_path_to_image_file . "\"" . "\r\n" .
"Content-Type: image/jpeg" . "\r\n" .
"\r\n" . // <- empty line is required
(file_get_contents($full_path_to_image_file)) . "\r\n" .
"--{$boundary}--";
The above will produce a request that looks like this:
-----------------------51b62743876b1201aee47ff4b1910e49
Content-Disposition: form-data; name="image_data"; filename="/some/directory/image.jpg"
Content-Type: image/jpeg
����
-----------------------51b62743876b1201aee47ff4b1910e49--
-- Technically speaking, the Content-Type in the request must change with the type of image you're uploading (image/jpeg or image/png). You can set the content type to application/octet-stream to cover all basis.
-----------------------51b62743876b1201aee47ff4b1910e49
Content-Disposition: form-data; name="image_data"; filename="/some/directory/image.jpg"
Content-Type: application/octet-stream
����
-----------------------51b62743876b1201aee47ff4b1910e49--
The two examples above will upload an image.
-- 'Image binary data' can be misleading as my every search showed that an image binary is obtained by using the base64_encode function. In my experiments, the base64_encoding doesn't do anything. You only need to open the file with the file_get_contents.
-- In your cURL request, must have the header's Content-Type set to multipart/form-data and have the same boundary as the request. Example below:
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Authorization: Bearer ' . $personalAccessToken, 'Content-Type: multipart/form-data; boundary=' . $boundary ));
So this adds another solution to the mix.
Troy's solution using # is deprecated and I was unable to get it to work. Byron's solution works with the CURLOPT_POST before the CURLOPT_POSTFIELDS (see Mavooks comment at https://www.php.net/manual/en/function.curl-setopt.php) and removing the Content-Type from the header. That is because it is automatically multipart if CURLOPTS_POSTFIELDS is an array and manually including it seems to override it, but then it is missing the boundary.
$square_url = 'https://connect.squareup.com/v1/me/items/' . $square_item_id . '/image';
$cfile = new CURLFile($image_path_on_server, 'image/png', 'image_data');
$image_data = array('image_data' => $cfile);
$curl = curl_init();
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Authorization: Bearer ' . $access_token,
'Accept: application/json'
));
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, $image_data);
curl_setopt($curl, CURLOPT_URL, $square_url);
curl_setopt($curl, CURLOPT_SAFE_UPLOAD, TRUE);
curl_setopt($curl, CURLOPT_BINARYTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($curl, CURLINFO_HEADER_OUT, TRUE);
curl_setopt($curl, CURLOPT_VERBOSE, TRUE);
$json = curl_exec($curl);
curl_close($curl);

Token invalid - Error 401 in YouTube API

I am Working send message using youtuba api. But i got a Error on my file. it shows Invalid Token 401 Error. My file is given below.I'm pretty sure I must be missing something vital but small enough to not notice it.
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://www.google.com/accounts/ClientLogin");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$data = array('accountType' => 'GOOGLE',
'Email' => 'User Email',
'Passwd' => 'pass',
'source'=>'PHI-cUrl-Example',
'service'=>'lh2');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$kk = curl_getinfo($ch);
$response = curl_exec($ch);
list($auth, $youtubeuser) = explode("\n", $response);
list($authlabel, $authvalue) = array_map("trim", explode("=", $auth));
list($youtubeuserlabel, $youtubeuservalue) = array_map("trim", explode("=", $youtubeuser));
$developer_key = 'AI39si7SavL5-RUoR0kvGjd0h4mx9kH3ii6f39hcAFs3O1Gf15E_3YbGh-vTnL6mLFKmSmNJXOWcNxauP-0Zw41obCDrcGoZVw';
$token = '7zWKm-LZWm4'; //The user's authentication token
$url = "http://gdata.youtube.com/feeds/api/users/worshipuk/inbox" ; //The URL I need to send the POST request to
$title = $_REQUEST['title']; //The title of the caption track
$lang = $_REQUEST['lang']; //The languageof the caption track
$transcript = $_REQUEST['transcript']; //The caption file data
$headers = array(
'Host: gdata.youtube.com',
'Content-Type: application/atom+xml',
'Content-Language: ' . $lang,
'Slug: ' . rawurlencode($title),
'Authorization: GoogleLogin auth='.$authvalue,
'GData-Version: 2',
'X-GData-Key: key=' . $developer_key
);
$xml = '<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:yt="http://gdata.youtube.com/schemas/2007">
<id>Qm6znjThL2Y</id>
<summary>sending a message from the api</summary>
</entry>';
// create a new cURL resource
$ch = curl_init();
// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, $url );
curl_setopt($ch, CURLOPT_HEADER, TRUE );
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, urlencode($xml) );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1 );
$tt = curl_getinfo($ch);
print_r($tt);
$result = curl_exec($ch);
print_r($result);
exit;
// close cURL resource, and free up system resources
curl_close($ch);
?>
any problem in my code? Please guide me. How can I get a result from this code?
Most likely your authentication is wrong, please debug that part first. Either you are not using right scope or that API is not enabled from your console.
On a separate note, I strongly suggest to use Youtube Data API v3 for this. We have updated PHP client library and great samples to get you started.

Categories