Принудительная загрузка с php на Amazon S3 - PullRequest
13 голосов
/ 15 мая 2009

Я пытаюсь использовать http://code.google.com/p/amazon-s3-php-class/ для принудительной загрузки файлов из AWS S3. У меня есть mp3, который я хочу, чтобы люди «играли» или «скачивали». По умолчанию, когда вы получаете доступ к файлу непосредственно на s3, он начинает воспроизводиться в браузере. Мне нужно добавить опцию, чтобы фактически загрузить. Я гуглил и нашел ничего не придумал. Я концептуально знаю, что должно произойти, но не знаю, как это сделать php. Я знаю, что мне нужно изменить заголовки на Content-Disposition: attachment. Любая помощь будет принята с благодарностью.

Спасибо, Michael

Ответы [ 12 ]

21 голосов
/ 06 мая 2011

Amazon теперь решил эту проблему и позволяет переопределять заголовки для каждого запроса подписанными запросами:

http://docs.amazonwebservices.com/AmazonS3/latest/API/index.html?RESTObjectGET.html

w00t!

10 голосов
/ 22 декабря 2009

Указанные выше php-скрипты будут работать нормально, но главный недостаток заключается в том, что каждый раз, когда посетитель вашего сайта запрашивает файл, ваши собственные серверы загружают его из S3 и затем передают эти данные в браузер. , Для сайтов с низким трафиком это, вероятно, не имеет большого значения, но для сайтов с высоким трафиком вам определенно нужно избегать запуска всего через ваши собственные серверы.

К счастью, есть довольно простой способ настроить ваши файлы для принудительной загрузки с S3. И вы совершенно правы - вы просто хотите установить тип контента и расположение контента (просто настройка контента размещения будет работать в некоторых браузерах, но настройка обоих должна работать во всех браузерах).

В этом коде предполагается, что вы используете PHP-класс Amazon S3 из Undesigned:

<?php

// set S3 auth and get your bucket listing

// then loop through the bucket and copy each file over itself, replacing the "request headers":
S3::copyObject($bucketName, $filename, $bucketName, $filename, "public-read", array(), array("Content-Type" => "application/octet-stream", "Content-Disposition" => "attachment"));

?>

Теперь все ваши файлы будут принудительно загружены. Вам может потребоваться очистить кэш, чтобы увидеть изменения. И, очевидно, не делайте этого ни с одним файлом, который вы действительно хотите загрузить «встроенным» в браузер.

Приятной особенностью этого решения является то, что приложения, которые загружают медиафайлы напрямую (например, mp3-плеер во Flash), не заботятся о типе контента или расположении контента, поэтому вы все равно можете воспроизводить файлы в браузер, а затем ссылку, чтобы загрузить этот же файл. Если пользователь уже завершил загрузку файла во флэш-памяти, он, скорее всего, все еще будет иметь его в своем кэше, что означает, что его загрузка будет очень быстрой и даже не потребует дополнительных затрат на пропускную способность от S3.

3 голосов
/ 07 апреля 2014

Просто желая опубликовать свой вклад в это, Алекс Нет прав в этой ссылке, но я не чувствую, что ссылка является достаточной информацией, используя AWS PHP SDK2 от Amazon. Ниже я описал базовый (непроверенный) метод для вызова данных таким образом, вы можете использовать либо S3 Factory Method, либо AWS Service Builder для создания S3 Client.

<?php
// S3 Factory Method
/*use Aws\S3\S3Client;

$s3= S3Client::factory(array(
    'key'    => '<aws access key>',
    'secret' => '<aws secret key>'
));*/

// OR AWS Service Builder
use Aws\Common\Aws;

// Create a service builder using a configuration file
$aws = Aws::factory('/path/to/my_config.json');

// Get the client from the builder by namespace
$s3 = $aws->get('S3');

// Now lets create our request object.
$command = $s3->getCommand('GetObject',array(
    'Bucket'                        => 'your-bucket-name',
    'Key'                           => 'keyname',
    'ResponseContentType'           => 'application/octet-stream',
    'ResponseContentDisposition'    => 'attachment; filename="filename.mp3',
));
$url = $command->createPresignedUrl('+1 days');
?>

Затем вы можете использовать заголовок PHP ("Location: $ url"); чтобы перенаправить посетителя в файл MP3 с принудительной загрузкой, это должно препятствовать его воспроизведению в браузере. Обратите внимание, что я довольно часто использую ResponseContentType, но я никогда не использовал ResponseContentDisposition с AWS (он должен работать в соответствии с документами ).

Преобразование этого примера в функцию должно быть простым, вы можете даже передать $ bucket, $ key, $ force_download как таковые

<?php
use Aws\Common\Aws;

function gen_url($bucket,$key,$force_download=false){
    // OR AWS Service Builder (personal method to do this)

    // Create a service builder using a configuration file
    $aws = Aws::factory('/path/to/my_config.json');

    // Get the client from the builder by namespace
    $s3 = $aws->get('S3');
    $params = array(
        'Bucket'                        => $bucket,
        'Key'                           => 'keyname',
        'ResponseContentType'           => 'application/octet-stream',
        'ResponseContentDisposition'    => 'attachment; filename="filename.mp3',
    );

    if($force_download){
        $params['ResponseContentType'] = 'application/octet-stream';
        $params['ResponseContentDisposition'] = 'attachment; filename="'.basename($key).'"';
    }

    $command = $s3->getCommand('GetObject',$params);
    return $command->createPresignedUrl('+1 days');
}

// Location redirection to an MP3 force downlaod
header("Location: ".gen_url("recordings","my-file.mp3",true));
// Location redirection to a MP3 that lets the browser decide what to do.
header("Location: ".gen_url("recordings","my-file.mp3"));

?>

ВНИМАНИЕ, если вы еще не поняли, для этого требуется AWS PHP SDK 2 (7 апреля 2014 г.), который можно найти здесь http://aws.amazon.com/sdkforphp/ Этот код в основном псевдокод, и для его выполнения может потребоваться дополнительная настройка работать, как я ссылаюсь на это из памяти.

3 голосов
/ 09 марта 2011

Просто добавьте это к метаданным вашего файла на s3:

Content-Disposition: attachment; filename=FILENAME.EXT
Content-Type: application/octet-stream
1 голос
/ 06 июня 2014
<?php
    require_once __DIR__.'/vendor/autoload.php';
    use Aws\Common\Aws;

    function gen_url($bucket,$key,$force_download=false){
        // OR AWS Service Builder (personal method to do this)


        $config = array(
                'key'    => '',
                'secret' => '',
        );

        // Create a service builder using a configuration file
        $aws = Aws::factory($config);

        // Get the client from the builder by namespace
        $s3 = $aws->get('S3');
        $params = array(
            'Bucket'                        => $bucket,
            'Key'                           => $key,
            'ResponseContentType'           => 'application/octet-stream',
            'ResponseContentDisposition'    => 'attachment; filename="'.$key,
        );

        if($force_download){
            $params['ResponseContentType'] = 'application/octet-stream';
            $params['ResponseContentDisposition'] = 'attachment; filename="'.basename($key).'"';
        }

        $command = $s3->getCommand('GetObject',$params);
        return $command->createPresignedUrl('+1 days');
    }

    $bucket = '';
    $filename = '';


    $url = gen_url($bucket,$filename,true);

    echo "\n".$url."\n\n";

Приведенный выше код работает, вам просто нужно установить зависимость S3 composer и ссылку в файле автозагрузки, поместить ваш ключ / секретный файл в конфигурацию и затем указать поле / имя файла.

1 голос
/ 08 сентября 2010

Также стоит упомянуть, что вы можете жестко установить заголовки для файлов в S3. Например, если вам нужно принудительно загрузить определенный файл, вы можете установить соответствующие заголовки для этого файла. Например, установка по умолчанию для потоковой передачи и установка дополнительного файла для принудительной загрузки или использование полосы пропускания для использования php / fputs и принудительной загрузки через PHP.

1 голос
/ 04 июня 2009

Если вы используете такую ​​библиотеку, как Tarzan AWS , вы можете добавить мета-заголовки, которые Amazon добавит при получении файла. Проверьте мета-параметр в функции update_object здесь, например: http://tarzan -aws.com / Docs / 2,0 / файлы / s3-класса php.html # AmazonS3.update_object

1 голос
/ 21 мая 2009

Так что измените мой пример выше, чтобы он был таким


<?php

header('Content-Type: audio/mpeg');
header("Content-Disposition: attachment; filename={$_GET['file']};");

readfile("url to the file/{$_GET['file']}");

exit();

?>

Теперь вы захотите добавить некоторую проверку, чтобы вы не давали миру доступ ко всем файлам, которые вы помещаете на S3, но это должно работать.

0 голосов
/ 15 сентября 2017

Теперь это возможно путем перезаписи заголовков S3 с использованием подписанных запросов.

Параметры запроса

В некоторых случаях вы хотите переопределить определенные значения заголовка ответа в ответе GET. Например, вы можете переопределить значение заголовка ответа Content-Disposition в вашем запросе GET.

Вы можете переопределить значения для набора заголовков ответов, используя параметры запроса, перечисленные в следующей таблице.

response-content-type - Устанавливает заголовок Content-Type ответа response-content-disposition - Устанавливает заголовок Content-Disposition ответа.

Примечание

При использовании этих параметров вы должны подписать запрос с использованием заголовка авторизации или предварительно подписанного URL-адреса. Их нельзя использовать с неподписанным (анонимным) запросом.

Итак, вы должны установить эти заголовки на:

response-content-disposition: attachment; filename=FILENAME.EXT
response-content-type: application/octet-stream

Нашел ответ здесь: https://stackoverflow.com/a/5903710/922522

0 голосов
/ 31 июля 2015
<?php
// PHP solution (for OP and others), works with public and private files
// Download url expires after 30 minutes (no experation after the download initiates, for large files)
// ***Forces client download***
$signed_url = $s3_client->getObjectUrl($s3_bucket_name, $s3_filename_key, '+30 minutes', array(
    'ResponseContentType' => 'application/octet-stream',
    'ResponseContentDisposition' => 'attachment; filename="your-file-name-here.mp4"'
));
redirect($signed_url);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...