Upload an AWS S3 file into Dropbox via PHP - php

I am using PHP to get my object from AWS S3 and then turn around and upload it into Dropbox. I can successfully get the object from AWS, but when I try and upload the file into Dropbox I just an empty Json reponse with no error or anything. I know that my $dbToken (Dropbox token) is working right because I can use the same key to get my folder structure and list files.
When I try and upload a file it just goes blank. I think it has to do with the AWS presigned URL. Do I need to make a Curl request to get the contents of that url ($secureUrl in my case). Not sure how to write that and how to get this file into Dropbox. Thanks for your help.
# ============================================
# Connect to AWS and get the Object
# This works fine...
# ============================================
$s3 = new S3Client([
'credentials'=>[
'key'=>xxxxxxx,
'secret'=>xxxxxxx,
],
'region'=>'us-west-2',
'version'=>'2006-03-01',
]);
$cmd = $s3->getCommand('GetObject', [
'Bucket' => xxxxxxx,
'Key' => xxxxxxx,
]);
$request = $s3->createPresignedRequest($cmd, '+60 seconds');
$secureUrl = (string) $request->getUri(); // get signed uri...
# echo $secureUrl; // if I echo this on the page, I can see the url, copy it and paste it into the browser and all works well...
# ============================================
# Connect To DropBox and Upload File...
# This is returning nothing in my output...
# ============================================
$dbToken = 'xxxxxxx';
$headers = [
"Authorization: Bearer ". $dbToken,
'Dropbox-API-Arg: {"path": "'.$secureUrl.'", "mode": "add", "autorename": true, "mute":false }',
"Content-Type: application/octet-stream"
];
$url = 'https://content.dropboxapi.com/2/files/upload';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, true);
$path = $secureUrl;
$fp = fopen($path, 'rb');
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
$result = curl_exec($ch);
$data = json_decode(trim($result), TRUE);
echo '<pre>';
print_r($data); // the json response is empty...
echo '</pre>';

Related

AWS WorkDocs : Your socket connection to the server was not read from or written to within the timeout period. Idle connections will be closed

I know there are similar cases to my problem but my case is about uploading a file with the WorkDocs API in php.
I saw that this problem could be related to the file size but mine is only 1KB.
I also saw that it could be a cURL bug (source: https://github.com/aws/aws-sdk-php/issues/29).
I call the initiateDocumentVersionUpload service and get the upload url:
$result = $client->initiateDocumentVersionUpload([
"Name" => "test-file.txt",
"ParentFolderId" => "***"
]);
$content = $result->get('UploadMetadata');
$url = $content['UploadUrl'];
And my curl request:
// The full path to the file that you want to upload
$filePath = 'C:/wamp64/www/test_aws/test-file.txt';
// Initiate cURL
$curl = curl_init($url);
// Set the URL
curl_setopt($curl, CURLOPT_URL, $url);
// Set the HTTP request to POST
curl_setopt($curl, CURLOPT_PUT, true);
//Tell cURL to return the output as a string.
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
//Open the file using fopen.
$fileHandle = fopen($filePath, 'r');
//Pass the file handle resorce to CURLOPT_INFILE
curl_setopt($curl, CURLOPT_INFILE, $fileHandle);
//Set the CURLOPT_INFILESIZE option.
curl_setopt($curl, CURLOPT_INFILESIZE, filesize($filePath));
$headers = array(
"Content-Type: application/octet-stream",
"x-amz-server-side-encryption: AES256"
);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
$data = "PUT request data";
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
// for debug only!
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$resp = curl_exec($curl);
curl_close($curl);
var_dump($resp);
And so I get the error: Your socket connection to the server was not read from or written to within the timeout period. Idle connections will be closed.
Do you know how I can fix this problem and upload my file ? Thanks in advance !
I've found another solution that works perfectly.
I've add the attribut 'verify' => false to the httpClient instance to avoid SSL issue.
$filePath = 'C:/wamp64/www/test_aws/test-file.txt';
$body = fopen($filePath, 'r');
$guzzle = new httpClient(['verify' => false]);
$upload = $guzzle->put($uploadUrl, [
'headers' => [
"Content-Type" => "application/octet-stream",
"x-amz-server-side-encryption" => "AES256"
],
'body' => $body
]);
Found the solution here: https://docs.aws.amazon.com/code-samples/latest/catalog/php-workdocs-UploadDocument.php.html

PHP Curl Post and Get Response

I have a shell code as below."curl -X POST -F 'file=#textomate-api.pdf;type=text/plain' https://textomate.com/a/uploadMultiple"
This code send a file to the URL and get the response below.
{
"countedFiles": [
{
"wordsNumber": 340,
"charsNumber": 2908,
"charsNoSpacesNumber": 2506,
"wordsNumberNN": 312,
"charsNumberNN": 2755,
"charsNoSpacesNumberNN": 2353,
"md5": null,
"fileName": "textomate-api.pdf",
"error": null
}
],
"total": {
"wordsNumber": 340,
"charsNumber": 2908,
"charsNoSpacesNumber": 2506,
"wordsNumberNN": 312,
"charsNumberNN": 2755,
"charsNoSpacesNumberNN": 2353,
"md5": null
}
}
And I want to post a file via PHP and get this response or only value of "charsNoSpacesNumber".
Could you please help me with this?
Thanks a lot
You can do it as follows:
YET be sure to first check their T&C as I am not sure if they provide such a service for free.
Also be sure to include some error / exceptions handling.
<?php
//Initialise the cURL var
$ch = curl_init();
//Get the response from cURL
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//Set the Url
curl_setopt($ch, CURLOPT_URL, 'https://textomate.com/a/uploadMultiple');
$path = '/path/to/your/file.pdf';
$file = curl_file_create($path, 'application/pdf', 'file');
//Create a POST array with the file in it
$postData = array(
'file' => $file,
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
// Execute the request, decode the json into array
$response = json_decode(curl_exec($ch), true);
var_dump($response['total']['charsNoSpacesNumber']);
Thanks for your support Bartosz.
This is my code and I also shared an image of the code and results.
I hope there are enough information.
<?php
if(is_callable('curl_init')){
echo "curl is active";
} else {
echo "curl is passive";
}
//Initialise the cURL var
$ch = curl_init();
//Get the response from cURL
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//Set the Url
curl_setopt($ch, CURLOPT_URL, 'https://textomate.com/a/uploadMultiple');
$path = 'textomate-api.pdf';
$file = curl_file_create($path, 'application/pdf', 'file');
//Create a POST array with the file in it
$postData = array(
'file' => $file,
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
// Execute the request, decode the json into array
$response = json_decode(curl_exec($ch), true);
var_dump($response['total']['charsNoSpacesNumber']);
var_dump($response);
var_dump(file_exists($path));
?>
Updated code is below and you can see the results in the image.
I want to use this API on my website to be able to calculate character count of documents. I am using Wordpress and API provider gives us 3 options, Java, PHP (Wordpress) and Shell. They have something for Wordpress but I don't know how to use it.
You can reach all the files from here.
https://github.com/zentaly/textomate-api
If you take a look there, you can get more information and maybe you can find me a better solution.
And again thank you so much for your support, I appreciate it.
<?php
if(is_callable('curl_init')){
echo "curl is active";
} else {
echo "curl is passive";
}
//Initialise the cURL var
$ch = curl_init();
//Get the response from cURL
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//Set the Url
curl_setopt($ch, CURLOPT_URL, 'https://textomate.com/a/uploadMultiple');
curl_setopt($ch, CURLOPT_VERBOSE, 2);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_exec: var_dump(curl_errno($ch));
var_dump(curl_error($ch));
$path = 'textomate-api.pdf';
$file = curl_file_create($path, 'application/pdf', 'file');
//Create a POST array with the file in it
$postData = array(
'file' => $file,
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
// Execute the request, decode the json into array
$response = curl_exec($ch);
var_dump($response);
$response = json_decode($ch);
var_dump($response['total']['charsNoSpacesNumber']);
var_dump($response);
var_dump(file_exists($path));
var_dump($file);
?>

cURL csv file submission returning OK status but no data is uploaded

I'm having difficulty uploading a .csv file through a cURL request to a RESTful API. I'm receiving a successful response (200 OK) but no data appears to be submitted:
{
"meta": [
],
"code": 200,
"object": "csvfile",
"data": [
],
"time": 1472464675
}
This is being made with the following request. I've added commenting to break down each of the CURL_SETOPTS:
// create a CURLFile object
$cfile = curl_file_create($fileName,'text/csv', $fileName);
// start curl request
$curl = curl_init();
// assign POST data
$data = array('file' => $cfile);
// specify POST request
curl_setopt($curl, CURLOPT_POST, true);
// basic auth
curl_setopt($curl, CURLOPT_USERPWD, getenv('USERNAME').':'.getenv('PASSWORD'));
// destination URI
curl_setopt($curl, CURLOPT_URL, 'https://api.arestfulapi.com');
// associate curlfile
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
// since we're using PHP 5.6 we need to enable CURLOPT_SAFE_UPLOAD
curl_setopt($curl, CURLOPT_SAFE_UPLOAD, true);
// return options
curl_setopt($curl, CURLOPT_RETURNTRANSFER,true);
curl_setopt($curl, CURLOPT_VERBOSE, true);
curl_setopt($curl, CURLOPT_STDERR, $out);
$response = curl_exec($curl);
$err = curl_error($curl);
// debugging
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo("CURL RESPONSE: ");
echo $response;
}
curl_close($curl);
I should mention I don't fully understand the importance of the $postname field in CURLfile objects. Furthermore I'm not entirely sure what I'm doing by assign POST data as demonstrated in the construct's documentation (http://php.net/manual/en/class.curlfile.php).
Note: I'm writing this in a Laravel application and am aware of the Guzzle client but have opted to present the problem this way, as there's more support for typical cURL problems on SO. I believe the issue is something to do with my cURLfile creation but have spent hours trying to pinpoint it.
What could be causing this issue?
I found a solution . I reworked the request using the Guzzle client again and eventually had success. Here's a copy of my solution:
// instantiate Guzzle http request
$client = new \GuzzleHttp\Client();
// provide an fopen resource
$filepath = 'public/'.$fileName;
$body = fopen($fileName, 'r');
// make the request
$res = $client->request('POST', 'https://api.website.com', [
'auth' => [
getenv('USERNAME'),
getenv('PASSWORD')
],
'body' => $body
]);
echo ("STATUS CODE: ");
echo $res->getStatusCode();
// 200

Uploading files using PHP

I have set up an HTML form to select a file and submit it to a PHP script which will upload it. I cannot use move_uploaded_files() because Box's API requires that I add a HTTP Header for Authorization: access_token. What I've done is set up my own POST method using the cURL library.
The problem I'm running into is setting the filename correctly, as it requires the full path of the file. I cannot get the full path of the file from the HTML form and using $_FILES['filename']['tmp_name'] uploads a .tmp file which I do not want. Does anyone know the solution to this problem? Thanks a lot!
My code:
public function upload_file($file) {
$url = 'https://api.box.com/2.0/files/content';
$params = [
'filename' => '#'.$file['tmp_name'],
'folder_id' => '0'
];
$header = "Authorization: Bearer ".$this->access_token;
$data = $this->post($url, $params, $header);
}
public function post($url, $params, $header='') {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
if(!empty($header)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, array($header));
}
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
Suggest you do one of the following:
Use move_uploaded_files to upload file into some directory and use that location to send the file to box using curl. After successful upload you can delete the file from this directory.
Instead of uploading the file through PHP, you can upload them client side using the cors http://developers.blog.box.com/2013/05/13/uploading-files-with-cors/
Another question which I have in my mind is how are you keeping your access_token refreshed?
Vishal
I agree with what Vishal has suggested in point number one.
I have written the PHP SDK for v2
Just include the api class and initiate the class:
<?php
include('library/BoxAPI.class.php');
$client_id = 'CLIENT ID';
$client_secret = 'CLIENT SECRET';
$redirect_uri = 'REDIRECT URL';
$box = new Box_API($client_id, $client_secret, $redirect_uri);
if(!$box->load_token()){
if(isset($_GET['code'])){
$token = $box->get_token($_GET['code'], true);
if($box->write_token($token, 'file')){
$box->load_token();
}
} else {
$box->get_code();
}
}
// Upload file
$box->put_file('RELATIVE FILE URL', '0'));
?>
Have a look here
Download: BoxPHPAPI

Upload external file to AWS S3 bucket using PHP SDK

I want to upload a file from an external URL directly to an Amazon S3 bucket using the PHP SDK. I managed to do this with the following code:
$s3 = new AmazonS3();
$response = $s3->create_object($bucket, $destination, array(
'fileUpload' => $source,
'length' => remote_filesize($source),
'contentType' => 'image/jpeg'
));
Where the function remote_filesize is the following:
function remote_filesize($url) {
ob_start();
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, 1);
$ok = curl_exec($ch);
curl_close($ch);
$head = ob_get_contents();
ob_end_clean();
$regex = '/Content-Length:\s([0-9].+?)\s/';
$count = preg_match($regex, $head, $matches);
return isset($matches[1]) ? $matches[1] : "unknown";
}
However, it would be nice if I could skip setting the filesize when uploading to Amazon since this would save me a trip to my own server. But if I remove setting the 'length' property in the $s3->create_object function, I get an error saying that the 'The stream size for the streaming upload cannot be determined.' Any ideas how to solve this problem?
You can upload file from url directly to Amazon S3 like this (my example is about a jpg picture):
1. Convert the content from url in binary
$binary = file_get_contents('http://the_url_of_my_image.....');
2. Create an S3 object with a body to pass the binary into
$s3 = new AmazonS3();
$response = $s3->create_object($bucket, $filename, array(
'body' => $binary, // put the binary in the body
'contentType' => 'image/jpeg'
));
That's all and it's very fast. Enjoy!
Do you have any control over remote server/host?. If so you could set up a php server to query the file locally and pass the data to you.
If not, you could use something like curl to inspect the header like so;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://sstatic.net/so/img/logo.png');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_exec($ch);
$size = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
var_dump($size);
This way, you are using a HEAD request, and not downloading the whole file -- still, you depend on the remote server send a correct Content-length header.

Categories