Dropbox v2 API - large file uploads - php

This question follows on from my previous question on the same subject. Simple file uploads are, well, simple.
$headers = array("Authorization: Bearer dropbox_token",
'Content-Type: application/octet-stream',
'Dropbox-API-Arg: {"path":"/path/file.ext",
"mode":"add"}');
$data = "I love Stackoverflow";
$ch = curl_init('https://content.dropboxapi.com/2/files/upload/');
curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);
curl_setopt($ch,CURLOPT_POST,true);
curl_setopt($ch,CURLOPT_POSTFIELDS,$data);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
However, this is not a viable option when the file data to be save run into 10s of megabytes. I thought I would simply use the new(ish) PHP curl_file_create.
$headers = array("Authorization: Bearer Dropbox token",
'Content-Type: application/octet-stream',
'Dropbox-API-Arg: {"path":"/path/bigfile.txt",
"mode":"add"}');
$ch = curl_init('https://content.dropboxapi.com/2/files/upload/');
curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);
$args['file'] = curl_file_create('/path/to/bigfile.txt');
curl_setopt($ch,CURLOPT_POST,true);
curl_setopt($ch,CURLOPT_POSTFIELDS,$args);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
However, this does not work. The Dropbox API returns the message
Error in call to API function "files/upload": Bad HTTP "Content-Type" header: "application/octet-stream; boundary=--... Expecting one of "application/octet-stream", "text/plain; charset=dropbox-cors-hack
I would be most grateful to anyone who could tell me where I might be going wrong here.

It looks like curl_file_create encodes a file as a multipart form upload, which isn't what you want when talking to the Dropbox API.
If I understand correctly, the issue you're trying to address is that you don't want to load the entire file contents into memory. Is that right?
If so, please give the following a try. (Apologies that I haven't tested it at all, so it may contain mistakes.)
$headers = array('Authorization: Bearer Dropbox token',
'Content-Type: application/octet-stream',
'Dropbox-API-Arg: {"path":"/path/bigfile.txt",
"mode":"add"}');
$ch = curl_init('https://content.dropboxapi.com/2/files/upload');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, true);
$path = '/path/to/bigfile.txt';
$fp = fopen($path, 'rb');
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($path));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
fclose($fp);
echo $response;
Note that you may also want to consider /files/upload_session_start, etc. if you're uploading large files. That lets you upload in chunks, and it supports files bigger than 150MB (which /files/upload does not).

If anyone interested a quick fix on Dropbox API v2 which CURLOPT_INFILE is not working, go to this link Dropbox PHP v2 upload issue
Greg explain and suggested to used this code curl_setopt($ch, CURLOPT_POSTFIELDS, fread($fp, $filesize)) instead of curl_setopt($ch, CURLOPT_INFILE, $fp);

Related

How to stop PHP cURL upload inserting "Boundary" into the "Content-Type" field?

I'm using the below code to upload an MP4 file to a web service, using PHP cURL.
I've specified the 'Content-Type' as 'video/mp4', in CURLOPT_HTTPHEADER.
Unfortunately, having uploaded the file, the 'Content-Type' stored for it in the service displays as: "content_type":"video/mp4; boundary=----WebKitFormBoundaryfjNZ5VkJS8z3CB9X"
As you can see, the 'boundary' has been inserted into the 'content_type'.
When I then download the file, it fails to play, with a 'file unsupported/file extension incorrect/file corrupt' message.
$authorization = "Authorization: Bearer [token]";
$args['file'] = curl_file_create('C:\example\example.mp4','video/mp4','example');
$url='[example web service URL]';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: multipart/form-data', 'Accept: application/vnd.mendeley-content-ticket.1+json', $authorization));
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS , $args);
$response = curl_exec($ch); // URL encoded output - needs to be URL encoded to get the HREF link header
curl_close($ch);
Would be extremely grateful for any help, advice or pointers!
Maybe the API doesn't expects a POST multipart, but the actual contents in the body itself:
Ref: How to POST a large amount of data within PHP curl without memory overhead?
You need to use PUT method for the actual contents of the file to go inside the body - if you use POST, it will try to send as a form.
$authorization = "Authorization: Bearer [token]";
$file = 'C:\example\example.mp4';
$infile = fopen($file, 'r');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.mendeley.com/file_contents");
curl_setopt($ch, CURLOPT_PUT, 1 ); // needed for file upload
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($file));
curl_setopt($ch, CURLOPT_INFILE, $infile);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST' );
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: video/mp4', 'Accept: application/vnd.mendeley-content-ticket.1+json', $authorization));
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec ($ch);
I have the same problem calling a Openai API from PHP curl.
I send options: Content-Type and Authorization (with my api key) but, when I send request, I receive this error:
Invalid Content-Type header (application/json; boundary=------------------------66a0b850cd1421c8), expected application/json
I tried to use some of your options with no success.
I cannot remove the boundary parameter added automatically.

Json save data to JSON file from API using PHP (curl)

I have written this code to get data from API URL.
All data is written to my file, but I can't find solution to make it look like Json format in file, what I am missing? Everything I tried in file showing like text (Added example below) and what I want. Maybe someone will help me with this :). Thanks!
Source code using php curl to get and save data
<?php
$token = "eyJ";
$ch = curl_init("https://api.xxx.com/api/Catelo/Prod?cat=MPHEFGZ");
$fp = fopen("prod.json", "w");
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Authorization: Bearer ' . $token
));
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
fclose($fp);
?>
I want it to save to file like this:
What I expect (saved format):
"FIFA_Last_World_Cup_final":
{
"Year": "2018",
"data":
{
"Winner": "France",
"Score": "4-2",
"Runner-up": "Croatia"
}
}
What I get now when data is saved to file:
[{"id":1,"Code":1,"name":"TV","manu":"32","v":"P","v":"P","c":"T","q":"0","p":1.0,"d":1.0,"imagePath":"e0bc7.Jpeg","thumbnailImagePath":"0bc7.Jpeg","fullDsc":"32\"","cury":"E","httpD":"548","packy":1,"ty":"24","eae":"","obligaKit":0,"reerty":0,"proate":0,"pront":70,"quane2":"0","pri":0.0,"lotN":"","p":0.0,"i":70}
As you are not processing the response from the API, what you see is just how the response is sent. To format it, you can capture the output (using CURLOPT_RETURNTRANSFER) and then decode the response - re-encoding it with JSON_PRETTY_PRINT.
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Authorization: Bearer ' . $token
));
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Store the JSON from the API
$response = curl_exec($ch);
curl_close($ch);
fclose($fp);
// Decode it, re-encode with formatting
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);

Twitter API token request returning gobbledygook

I'm trying to use Application Only Authentication, as described here:
https://developer.twitter.com/en/docs/basics/authentication/overview/application-only
I'm using the following PHP code to do so.
if(empty($_COOKIE['twitter_auth'])) {
require '../../social_audit_config/twitter_config.php';
$encoded_key = urlencode($api_key);
$encoded_secret = urlencode($api_secret);
$credentials = $encoded_key.":".$encoded_secret;
$encoded_credentials = base64_encode($credentials);
$request_headers = array(
'Host: api.twitter.com',
'User-Agent: BF Sharing Report',
'Authorization: Basic '.$encoded_credentials,
'Content-Type: application/x-www-form-urlencoded;charset=UTF-8',
'Content-Length: 29',
'Accept-Encoding: gzip'
);
print_r($request_headers);
$ch = curl_init();
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_URL, 'https://api.twitter.com/oauth2/token');
curl_setopt($ch, CURLOPT_POSTFIELDS, 'grant_type=client_credentials');
$attempt_auth = curl_exec($ch);
print_r($attempt_auth);
}
It should return JSON with the token in it, but instead it returns gobbledygook, as seen in the image below:
I'm sure I'm missing some very simple step, where am I going wrong?
If I send the curl request without the headers, it returns an error in JSON format as expected, so is there something wrong with my headers?
You have few options here. Instead of setting header directly, use below
curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
If you set header directly then you should use
print_r(gzdecode($attempt_auth));
See below thread as well
Decode gzipped web page retrieved via cURL in PHP
php - Get compressed contents using cURL

Dropbox list_folder call doesn't work in PHP_cURL

I'm trying to detect all of the subfolders in a given directory, using the PHP_CURL library to interact with the Dropbox API. I think this is just a syntax issue, with the JSON body of the call, but I don't know what's wrong.
$url = "https://api.dropboxapi.com/2/files/list_folder";
$data = array('path' => '/root/folder');
$post_body = json_encode($data);
print_r( $post_body );
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Bearer ' . $token,
'Content-Type: application/json') );
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_body);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($data);
Here is the output:
{"path":"\/root\/folder"}
There are definitely folders in that directory, but nothing beyond my debug shows up when I run this from command line-- no errors, or anything. It also works just fine when I run it with Postman. Meanwhile, my file-upload testing script works perfectly, so I know there's no problem with my authorization token.
Why is my code broken?
The correct API URL for listing the subfolders is:
https://api.dropboxapi.com/2/files/list_folder
I copy/pasted the file-upload URL, which was:
https://content.dropboxapi.com/2/files/list_folder
So it was a syntax error, just not where I was looking for it.

Uploading track with curl, echonest POST issue with local file

I am trying to upload a file (input type and named "upload") through the echonest api but am struggling to get the curl upload working.
http://developer.echonest.com/docs/v4/track.html#upload
Can anybody point me into the right direction to get the data-binary and header: application/octet-stream POST method working.
This A HTTP POST request with Content-Type "application/octet-stream", with the local file as the body of the request, and the parameters in the URL.
the curl php:
$localfile = $_FILES['upload']['name'];
$fp = fopen($localfile, 'r');
$post = array('$localfile'=>'#$localfile','api_key'=>'xx','filetype'=>'mp3');
$ch = curl_init();
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); // --data-binary
curl_setopt($ch, CURLOPT_URL, 'http://developer.echonest.com/api/v4/track/upload');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_HTTPHEADER, 'Content-type: application/octet-stream');
$response = curl_exec($ch);
$result = json_decode($response,true);
$id = $result['response']['track']['id'];
curl_close($ch);
fclose($fp);
echo $id;
The problem might have something to do with your use of variables inside a single-quoted string. Also, improper use of the # symbol. Try this...
array("$localfile"=>"$localfile",'api_key'=>'xx','filetype'=>'mp3');
Though that doesn't look right either. You probably want this..
array("localfile"=>"$localfile",'api_key'=>'xx','filetype'=>'mp3');

Categories