Pergunta

Eu estou tentando usar http://code.google.com/ p / amazon-s3-php-classe / para arquivos força-dowload de AWS S3. Eu tenho um mp3 que eu quero que as pessoas a "brincar" ou "download." Por padrão, o quando você acessar o arquivo diretamente no s3 ele começa a jogar no browser. Eu preciso adicionar uma opção para realmente download. Eu pesquisei e encontrei veio com nada. I conceitualmente sabe o que precisa acontecer, mas não sabe como produzir php. Eu sei que eu preciso modificar os cabeçalhos para Content-Disposition: anexo. Qualquer ajuda seria muito apreciada.

Obrigado, Michael

Foi útil?

Solução

Os scripts PHP que foram mencionados até agora irá funcionar ok, mas a principal desvantagem é que cada vez que um visitante em seu site solicita um arquivo, seus próprios servidores irá carregá-lo a partir do S3 e depois retransmitir os dados para o navegador . Para sites de baixo tráfego, provavelmente não é um grande negócio, mas para aqueles de alto tráfego, você definitivamente quer evitar correr tudo através de seus próprios servidores.

Felizmente, há uma maneira bastante simples para definir seus arquivos para ser forçado a transferência a partir do S3. E você está absolutamente certo - você só quer definir o tipo de conteúdo e conteúdo-disposição (apenas a criação de disposição do conteúdo vai funcionar em alguns navegadores, mas a definição de ambos deve funcionar em todos os navegadores)

.

Este código é assumindo que você está usando a classe Amazon S3 PHP a partir 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"));

?>

Agora, todos os arquivos serão forçados a download. Pode ser necessário limpar o cache para ver a mudança. E, obviamente, não faça isso em qualquer arquivo que você realmente quer ser carregado "inline" no navegador.

A parte agradável com esta solução é que os aplicativos que arquivos de mídia de carga diretamente (como o vamos dizer um mp3 player em Flash) não se preocupam com o tipo de conteúdo ou conteúdo-disposição, assim você ainda pode reproduzir seus arquivos na browser e, em seguida, link para baixar o mesmo arquivo. Se o usuário de carregamento já acabado o arquivo em flash, eles provavelmente ainda vai tê-lo em seu cache, o que significa que o seu download será super rápido e não vai mesmo custar-lhe quaisquer encargos largura de banda extra a partir do S3.

Outras dicas

Amazon já resolveu este problema e permite substituir de cabeçalhos em uma base per-request com pedidos assinados:

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

w00t!

Apenas adicione aos metadados do seu arquivo no S3:

Content-Disposition: attachment; filename=FILENAME.EXT
Content-Type: application/octet-stream

Apenas querendo postar uma contribuição para isso, Alex Neth está correto nessa referência, mas eu não me sinto um link é informação suficiente, usando da Amazon AWS próprio PHP SDK2. Abaixo eu esbocei um método básico (não testado) para chamar dados desta forma, você pode usar o S3 Factory Method ou AWS Service Builder para tornar o S3 cliente.

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

Você pode então usar cabeçalho do PHP ( "Location: $ url"); a fim de redirecionar o visitante para o arquivo MP3 com um download vigor, isso deve impedi-lo de jogar no navegador, por favor note, eu uso ResponseContentType bastante freqüência, mas eu nunca usei ResponseContentDisposition com AWS (ele deve funcionar de acordo com os docs ).

Convertendo este exemplo em uma função deve ser fácil, você poderia até mesmo passar em $ balde, $ key, $ force_download como tal

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

?>

ATENÇÃO, se você ainda não percebi isso, isto requer a AWS PHP SDK 2 atualmente (07 abril de 2014) encontrado aqui http://aws.amazon.com/sdkforphp/ este código é principalmente pseudo-código e pode exigir alguns ajustes adicionais para realmente fazer o trabalho que eu estou fazendo referência este da memória.

Assim, modificar o meu exemplo acima que ser assim


<?php

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

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

exit();

?>

Agora você vai querer colocar alguma validação lá para que você não dar o mundo acesso a todos os arquivos que você colocar no S3, mas isso deve funcionar.

Se você estiver usando uma biblioteca como Tarzan AWS , você pode adicionar meta cabeçalhos, que a Amazon irá incluir quando o arquivo é recuperado. Confira o parâmetro meta na função update_object aqui, por exemplo: http://tarzan-aws.com/ docs / 2.0 / arquivos / s3-class-php.html # AmazonS3.update_object

Também vale a pena mencionar é que você é capaz de hard-set os cabeçalhos de arquivos em S3. Por exemplo, se você precisa de força de fazer download de um determinado arquivo você pode definir os cabeçalhos apropriados para esse arquivo. Tais como falta de fluxo, e quer ter um conjunto de arquivos secundário a força-download ou passar a largura de banda para usar o PHP / fputs e força de download via PHP.

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

O código acima funciona, você só precisa instalar a dependência compositor S3 e link no arquivo autoload, coloque a chave / segredo em config e, em seguida, fornecer o balde / filename.

php seria apenas baixar o arquivo para o servidor, não o cliente. lembre-se, php não faz nada no cliente, ele só retorna conteúdo (HTML, JavaScript, CSS, XML, qualquer que seja ...)

[edit: adicionado para maior clareza]: php pode servir conteúdo de áudio, mas você quer servir uma página web e áudio ao mesmo tempo. Para obter esse comportamento do cliente, você tem que obter o cliente para solicitar o arquivo com base na página web html ou javascript.

Então você tem que obter o cliente para baixar o arquivo. Por exemplo, tem um iframe na página com a URL do arquivo no S3. Use CSS para fazer o iframe invisível. Ele deve processar a página e baixar e jogar o mp3.

Caso contrário, olhar para usar javascript para chutar de um download quando a página é carregada. Eu não tenho certeza se isso é possível.

Esta é agora possível, substituindo os cabeçalhos S3 usando pedidos assinados.

Parâmetros de solicitação

Há momentos em que você deseja substituir determinados valores de cabeçalho de resposta em uma resposta GET. Por exemplo, você pode substituir o valor de cabeçalho de resposta Content-Disposition no seu pedido GET.

Você pode substituir os valores para um conjunto de cabeçalhos de resposta, utilizando os parâmetros de consulta listados na tabela a seguir.

resposta-tipo de conteúdo - Define o cabeçalho Content-Type da resposta resposta-conteúdo-disposition -. Define o cabeçalho Content-Disposition da resposta

Nota

Você deve assinar o pedido, quer utilizando um cabeçalho de autorização ou de um URL pré-assinado, ao usar estes parâmetros. Eles não podem ser usados ??com um sem assinatura (anônimo) pedido.

Assim, você definiria esses cabeçalhos para:

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

resposta encontrada aqui: https://stackoverflow.com/a/5903710/922522

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

Eu nunca tentei S3 da Amazon hospedagem, mas você não tem acesso ao uso de arquivos .htaccess lá? Em seguida, você pode definir Content-Type e Content-Disposition para um diretório inteiro com esta entrada:

<IfModule mod_headers.c>
    <FilesMatch "\.(mp3)$">
            ForceType audio/mpeg
            Header set Content-Disposition attachment
    </FilesMatch>
</IfModule>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top