使用 php 从 Amazon s3 压缩和下载文件

Posted

技术标签:

【中文标题】使用 php 从 Amazon s3 压缩和下载文件【英文标题】:Zip and download files from Amazon s3 with php 【发布时间】:2014-12-01 04:42:50 【问题描述】:

我正在使用托管在 Amazon Elastic Beanstalk 上的 php 创建我的第一个 Web 应用程序,但我有点不知所措。我的任务是访问最终客户在 AWS S3 云中指定的文件,将它们压缩,最后提供生成的 zip 文件的下载链接。我已经四处寻找一个我正在尝试做的事情的实例,但是我对 php 的缺乏经验一直是我确定某个解决方案是否适合我的障碍。

我发现了这个问题和回复here,并且看到它似乎在一般意义上解决了 php 和 zip 下载,我想我可能能够适应我的需要。以下是我在 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);

这是我用来称呼它的:

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

我也试过了:

$(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;
        );
    );

现在,每当我单击下载按钮时,我都会收到“开始 zip 测试”的回声,而没有其他任何内容。没有错误,也没有 zip 文件。我需要知道什么或我做错了什么?

提前感谢您的帮助和建议。

编辑: 以下是我在听取了 Derek 的建议后得到的。这仍然会产生一大串讨厌的二进制文件。

<?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);
?>

【问题讨论】:

你正在使用popen,这意味着你正在执行一个外部程序。命令行应用程序绝对知道s3://etc... 是什么意思。他们不处理 URL。他们处理文件系统路径。如果您在 unix/windows 上,您最多可以使用 NFS 或 UNC 路径。 【参考方案1】:

Marc B 的评论是正确的。对 zip 的调用不知道 s3:// 是什么意思。

您需要从 S3 下载文件,然后将其压缩到本地。您有多种从 S3 下载文件的选项。例如,您可以使用:

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

获取对象的 URL,然后使用 cUrl 或 wget 从该 URL 下载,具体取决于您的权限设置。

在本地获得文件后,使用保存文件的位置更新 zip 命令以生成 .zip 文件。

【讨论】:

感谢您的提示,德里克。我已将脚本更改为使用 S3 的 getObject() 以及将文件保存在本地存储中的选项。引用本地目录中文件的位置似乎会像我希望的那样创建一个 zip 包,但是当我回显结果时,我得到一个代表我的 zip 文件的巨大二进制字符串,而不是提示下载它。我尝试将 Content-type 标头更改为 application/zip,但无济于事。我还能错过什么? 您是否在 header('Content-type: ...') 行之前回显了任何内容?或者,如果没有,您的页面是否在开头的 仍然没有骰子。我已将我的脚本缩减为必需品并尝试了您的建议。我已经用我目前拥有的内容编辑了我的原始帖子。我唯一能想到的是,也许我用来调用 php 脚本的 jquery 是罪魁祸首?如果你看不出它有什么问题,我可能不得不寻找另一种方法。感谢您的帮助。 我认为问题在于: echo "Starting zip test";您在内容标题之前向浏览器发送响应,因此标题被忽略。 我在原帖下方添加了一个编辑。在您发表第一条评论后,我删除了那个回声声明。很抱歉造成混乱。

以上是关于使用 php 从 Amazon s3 压缩和下载文件的主要内容,如果未能解决你的问题,请参考以下文章

使用send_file从Amazon S3下载文件吗?

Drupal 7聚合并压缩CSS / JS不能与Amazon S3一起使用

如何使用 Amazon S3 创建一次性下载链接?

从 Amazon S3 下载 res.download 文件

使用 AWS 开发工具包从 Amazon S3 下载文件后如何删除文件

WinHttp 不会从 WinXP 上的 Amazon S3 下载