Force-Download con php en Amazon S3

Intento utilizar http://code.google.com/p/amazon-s3-php-class/ para forzar archivos de descargas de AWS S3. Tengo un mp3 que quiero que la gente “juegue” o “descargue”. Por defecto, cuando accede al archivo directamente en s3, comienza a reproducirse en el navegador. Necesito agregar una opción para descargar realmente. Busqué en Google y encontré nada. Conceptualmente sé lo que debe suceder pero no sé cómo producirlo php. Sé que necesito modificar los encabezados a Content-Disposition: archivo adjunto. Cualquier ayuda sería muy apreciada.

Gracias, Michael

Las secuencias de comandos php que se han mencionado hasta ahora funcionarán bien, pero la desventaja principal es que cada vez que un visitante en su sitio solicita un archivo, sus propios servidores lo cargarán desde el S3 y luego transmitirán esos datos al navegador. Para sitios de poco tráfico, probablemente no es un gran problema, pero para los de mucho tráfico, definitivamente desea evitar ejecutar todo a través de sus propios servidores.

Afortunadamente, hay una manera bastante sencilla de configurar sus archivos para que se los fuerce a descargar desde el S3. Y está exactamente en lo cierto: solo desea establecer el tipo de contenido y la disposición del contenido (basta con configurar el contenido: la disposición funcionará en algunos navegadores, pero la configuración de ambos debería funcionar en todos los navegadores).

Este código supone que está utilizando la clase PHP de Amazon S3 desde Undesigned:

 "application/octet-stream", "Content-Disposition" => "attachment")); ?> 

Ahora todos sus archivos se verán obligados a descargar. Es posible que deba borrar su caché para ver el cambio. Y obviamente, no hagas eso en ningún archivo que realmente quieras cargar “en línea” en el navegador.

Lo bueno de esta solución es que las aplicaciones que cargan archivos multimedia directamente (como, por ejemplo, un reproductor de mp3 en Flash) no se preocupan por el tipo de contenido o la disposición del contenido, por lo que aún puede reproducir sus archivos en el navegador y luego enlace para descargar ese mismo archivo. Si el usuario ya terminó de cargar el archivo en flash, lo más probable es que aún lo tenga en su caché, lo que significa que su descarga será súper rápida y que ni siquiera le costará ningún cargo adicional de ancho de banda del S3.

Amazon ahora ha resuelto este problema y permite anular encabezados por solicitud con solicitudes firmadas:

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

w00t!

Solo agregue esto a los metadatos de su archivo en s3:

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

Solo queriendo publicar una contribución a esto, Alex Neth tiene razón en esta referencia, pero no creo que un enlace sea suficiente información, utilizando el AWS PHP SDK2 de Amazon. A continuación, describí un método básico (no probado) para llamar a los datos de esta manera, puede usar el Método de fábrica S3 o el Creador de servicios de AWS para crear el Cliente S3.

  '', 'secret' => '' ));*/ // 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'); ?> 

Luego puede usar el encabezado de PHP (“Ubicación: $ url”); para redirigir al visitante al archivo MP3 con una descarga forzada, esto debería evitar que se reproduzca en el navegador. Tenga en cuenta que utilizo ResponseContentType con bastante frecuencia pero nunca he usado ResponseContentDisposition con AWS (debería funcionar de acuerdo con los documentos). )

Convertir esta muestra en una función debería ser fácil, incluso podría pasar $ bucket, $ key, $ force_download como tal

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

ADVERTENCIA, si no lo ha descubierto, esto requiere que AWS PHP SDK 2 actualmente (7 de abril de 2014) se encuentre aquí http://aws.amazon.com/sdkforphp/ Este código es en su mayoría pseudocódigo y puede requerir ajustes adicionales para hacer realmente el trabajo ya que estoy haciendo referencia a esto desde la memoria.

Así que modifica mi ejemplo anterior para que sea así

  

Ahora querrá poner algo de validación allí para no darle acceso al mundo a cada archivo que ponga en S3, pero esto debería funcionar.

Si está utilizando una biblioteca como Tarzán AWS , puede agregar meta encabezados, que Amazon incluirá cuando se recupere el archivo. Consulte el metaparámetro en la función update_object aquí, por ejemplo: http://tarzan-aws.com/docs/2.0/files/s3-class-php.html#AmazonS3.update_object

También vale la pena mencionar que puede configurar los encabezados para los archivos en S3. Por ejemplo, si necesita forzar la descarga de un determinado archivo, puede establecer los encabezados apropiados para ese archivo. Por ejemplo, la opción predeterminada para transmitir y tener un archivo secundario configurado para forzar la descarga o gastar el ancho de banda para usar php / fputs y forzar la descarga a través de PHP.

  '', '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"; 

El código anterior funciona, solo necesita instalar la dependencia y el vínculo del compositor S3 en el archivo de carga automática, poner su clave / secreto en la configuración y luego suministrar el cubo / nombre del archivo.

php simplemente descargaría el archivo al servidor, no al cliente. recuerda, php no hace nada en el cliente, solo devuelve contenido (html, javascript, css, xml, lo que sea …)

[Editar: añadido para mayor claridad]: php puede servir contenido de audio, pero desea servir una página web y audio al mismo tiempo. Para obtener el comportamiento de ese cliente, debe hacer que el cliente solicite el archivo en función de html o javascript de la página web.

Entonces debes hacer que el cliente descargue el archivo. Por ejemplo, tenga un iframe en la página con la url del archivo en s3. Use css para hacer que el iframe sea invisible. Debería mostrar la página y descargar y reproducir el mp3.

De lo contrario, analice el uso de JavaScript para iniciar una descarga cuando se cargue la página. No estoy seguro si eso es posible.

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

Esto ahora es posible sobrescribiendo los encabezados S3 utilizando solicitudes firmadas.

Parámetros de solicitud

Hay momentos en los que desea anular ciertos valores de encabezado de respuesta en una respuesta GET. Por ejemplo, puede anular el valor del encabezado de respuesta Content-Disposition en su solicitud GET.

Puede anular valores para un conjunto de encabezados de respuesta utilizando los parámetros de consulta enumerados en la siguiente tabla.

response-content-type – Establece el encabezado Content-Type de la respuesta response-content-disposition – Establece el encabezado Content-Disposition de la respuesta.

Nota

Debe firmar la solicitud, ya sea utilizando un encabezado de Autorización o una URL firmada previamente, al usar estos parámetros. No se pueden usar con una solicitud sin firmar (anónima).

Entonces, debes establecer esos encabezados para:

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

La respuesta encontrada aquí: https://stackoverflow.com/a/5903710/922522

Nunca intenté el alojamiento S3 de Amazon, pero ¿no tienes acceso a usar archivos .htaccess allí? Luego puede establecer Content-Type y Content-Disposition para un directorio completo con esta entrada:

   ForceType audio/mpeg Header set Content-Disposition attachment