Zip and upload files from Amazon s3 with php

I am creating my first web application using php hosted on Amazon Elastic Beanstalk and I am a little over my head on what to do. My task is to access the files provided by the end user in the AWS S3 cloud, pin them, and finally provide the download link in the resulting zip file. I hunted a lot to find an instance of what exactly I am trying to do, but my inexperience with php was an obstacle in determining if some solution would work for me.

I found this question and answer here , and seeing that it seemed to address php and zip downloads in a general sense, I thought I could adapt it to my needs. Below is what I have in php:

<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);

require "./aws.phar";
use Aws\S3\S3Client;

$client = S3Client::factory(array(
    'key'    => getenv("AWS_ACCESS_KEY_ID"),
    'secret' => getenv("AWS_SECRET_KEY")
));

echo "Starting zip test";

$client->registerStreamWrapper();

// make sure to send all headers first
// Content-Type is the most important one (probably)
//
header('Content-Type: application/octet-stream');
header('Content-disposition: attachment; filename="file.zip"');

// use popen to execute a unix command pipeline
// and grab the stdout as a php stream
// (you can use proc_open instead if you need to 
// control the input of the pipeline too)
//
$fp = popen('zip -r - s3://myBucket/test.txt s3://myBucket/img.png', 'r');

// pick a bufsize that makes you happy (8192 has been suggested).
$bufsize = 8192;
$buff = '';
while( !feof($fp) ) {
   $buff = fread($fp, $bufsize);
   echo $buff;
}
pclose($fp);

      

And this is what I use to call it:

$(document).ready(function() {
    $("#download_button").click(function() {
        $.get("../php/ZipAndDownload.php", function(data){alert(data)});
        return false;
    });
});

      

I've also tried:

$(document).ready(function() {
        $("#download_button").click(function() {
            $.ajax({
                url:url,
                type:"GET",
                complete: function (response) {
                    $('#output').html(response.responseText);
                },
                error: function () {
                    $('#output').html('Bummer: there was an error!');
                }
            });
            return false;
        });
    });

      

Now when I click the download button, I get a "Run zip test" echo and nothing else. No errors and no zip file. What do I need to know, or what am I doing obviously wrong?

Thanks in advance for your help and advice.

EDIT: Here's what I have after some advice from Derek. This still creates a big nasty line of binary.

<?php
header('Content-Type: application/octet-stream');
header('Content-disposition: attachment; filename="file.zip"');

require "./aws.phar";
use Aws\S3\S3Client;

$bucket = 'myBucket';

$client = S3Client::factory(array(
    'key'    => getenv('AWS_ACCESS_KEY_ID'),
    'secret' => getenv('AWS_SECRET_KEY')
));

$result = $client->getObject(array(
    'Bucket' => $bucket,
    'Key'    => 'test.txt',
    'SaveAs' => '/tmp/test.txt'
));

$Uri = $result['Body']->getUri();

$fp = popen('zip -r - '.$Uri, 'r');

$bufsize = 8192;
$buff = '';
while( !feof($fp) ) {
   $buff = fread($fp, $bufsize);
   echo $buff;
}
pclose($fp);
?>

      

+3


source to share


1 answer


Marc B's comment is correct. The zip call doesn't know what s3: // means.

You will need to download the file from S3 and then upload it locally. You have several options for downloading the file from S3. For example, you can use:

$client->getObjectUrl($bucket, $key) 

      



to get the url for your object, then use cUrl or wget to download from that url depending on your permission settings.

Once you have the file locally, update your zip command using the location where you saved the file to generate the zip file.

+4


source







All Articles