Home » Php » Upload external file to AWS S3 bucket using PHP SDK

Upload external file to AWS S3 bucket using PHP SDK

Posted by: admin July 12, 2020 Leave a comment

Questions:

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?

How to&Answers:

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!

Answer:

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.