getobjecturl - putobject s3 php
PUT/Copiar con PHP, REST, Flex y Amazon S3 (1)
He intentado durante semanas formatear correctamente una REST request
para la Amazon AWS S3 API
utilizando los ejemplos disponibles en la web, pero no he podido conectarme con éxito.
Encontré el código para generar una firma, encontré el método adecuado para formatear la "cadena para codificar" y los http headers
. Me abrí paso a través de los errores de signatureDoesNotMatch
para que los Anonymous users can not perform copy functions, Please authenticate
mensaje.
Tengo una copia de trabajo de una aplicación de Adobe Flex
que carga archivos con éxito, pero con su nombre de archivo "original". El objetivo de usar REST
con la Amazon API
es realizar un PUT
(copia) del archivo, solo para poder cambiarle el nombre a algo que pueda usar mi sistema de fondo.
Si pudiera encontrar una manera de hacer que funcione este envío de REST
, o quizás una forma de especificar un "nuevo" nombre de archivo dentro de Flex
durante la carga, podría evitar toda esta situación de REST
conjunto.
Si alguien ha realizado con éxito un comando PUT/Copy
en la Amazon API
través de REST
, estaría muy interesado en cómo se logró esto. O, si alguien ha podido cambiar el nombre del archivo de destino utilizando el fileReference.browse()
Flex
fileReference.browse()
I también estaría eternamente agradecido por cualquier puntero.
El código PHP para esto es el siguiente:
$aws_key = ''removed_for_security'';
$aws_secret = ''removed_for_security'';
$source_file = $uploaded_s3_file; // file to upload to S3 (defined in above script)
$aws_bucket = ''bucket''; // AWS bucket
$aws_object = $event_file_name; // AWS object name (file name)
if (strlen($aws_secret) != 40) die("$aws_secret should be exactly 40 bytes long");
$file_data = file_get_contents($source_file);
if ($file_data == false) die("Failed to read file " . $source_file);
// opening HTTP connection to Amazon S3
$fp = fsockopen("s3.amazonaws.com", 80, $errno, $errstr, 30);
if (!$fp) die("$errstr ($errno)/n");
// Uploading object
$file_length = strlen($file_data); // for Content-Length HTTP field
$dt = gmdate(''r''); // GMT based timestamp
// preparing String to Sign (see AWS S3 Developer Guide)
// preparing string to sign
$string2sign = "PUT
{$dt}
/{$aws_bucket}/{$aws_object}";
// preparing HTTP query
// $query = "PUT /".$aws_bucket."/".$event_file_name." HTTP/1.1
$query = "PUT /" . $event_file_name . " HTTP/1.1
Host: {$aws_bucket}.s3.amazonaws.com
Date: {$dt}
x-amz-copy-source: /{$aws_bucket}/{$current_s3_filename}
x-amz-acl: public-read
Authorization: AWS {$aws_key}:" . amazon_hmac($string2sign) . "/n/n";
$query .= $file_data;
$resp = sendREST($fp, $query);
if (strpos($resp, '''') !== false) {
die($resp);
}
echo "FILE uploaded/n";
// done
echo "Your file''s URL is: http://s3.amazonaws.com/{$aws_bucket}/{$aws_object}/n";
fclose($fp);
// Sending HTTP query and receiving, with trivial keep-alive support
function sendREST($fp, $q, $debug = true){
if ($debug) echo "/nQUERY<<{$q}>>/n";
fwrite($fp, $q);
$r = '''';
$check_header = true;
while (!feof($fp)) {
$tr = fgets($fp, 256);
if ($debug) echo "/nRESPONSE<<{$tr}>>";
$r .= $tr;
if (($check_header) && (strpos($r, "/r/n/r/n") !== false)) {
// if content-length == 0, return query result
if (strpos($r, ''Content-Length: 0'') !== false) {
return $r;
}
}
// Keep-alive responses does not return EOF
// they end with /r/n0/r/n/r/n string
if (substr($r, -7) == "/r/n0/r/n/r/n") {
return $r;
}
}
return $r;
}
// hmac-sha1 code START
// hmac-sha1 function: assuming key is global $aws_secret 40 bytes long
// read more at http://en.wikipedia.org/wiki/HMAC
// warning: key($aws_secret) is padded to 64 bytes with 0x0 after first function call
function amazon_hmac($stringToSign) {
// helper function binsha1 for amazon_hmac (returns binary value of sha1 hash)
if (!function_exists(''binsha1'')) {
if (version_compare(phpversion(), "5.0.0", ">=")) {
function binsha1($d) { return sha1($d, true); }
} else {
function binsha1($d) { return pack(''H*'', sha1($d)); }
}
}
global $aws_secret;
if (strlen($aws_secret) == 40) {
$aws_secret = $aws_secret . str_repeat(chr(0), 24);
}
$ipad = str_repeat(chr(0x36), 64);
$opad = str_repeat(chr(0x5c), 64);
$hmac = binsha1(($aws_secret ^ $opad) . binsha1(($aws_secret ^ $ipad) . $stringToSign));
return base64_encode($hmac);
}
// hmac-sha1 code END
Cuando envío un encabezado mal formado o incorrecto, recibo el mensaje de error correspondiente como se esperaba:
Consulta:
PUT /bucket/1-132-1301047200-1.jpg Host HTTP / 1.1: s3.amazonaws.com x-amz-acl: public-read Conexión: keep-alive Longitud del contenido: 34102 Fecha: sáb, 26 mar 2011 00 : 43: 36 +0000 Autorización: AWS eliminado para seguridad: GmgRObHEFuirWPwaqRgdKiQK / EQ =
HTTP / 1.1 403 prohibido
x-amz-request-id: A7CB0311812CD721
x-amz-id-2: ZUY0mH4Q20Izgt / 9BNhpJl9OoOCp59DKxlH2JJ6K + sksyxI8lFtmJrJOk1imxM / A
Tipo de contenido: application / xml
Transferencia de codificación: fragmentada
Fecha: sáb, 26 mar. 2011 00:43:36 GMT
Conexión: cerrar
Servidor: AmazonS3
397 SignatureDoesNotMatchLa firma de solicitud que calculamos no coincide con la firma que proporcionó. Verifique su clave y el método de firma.50 55 54 0a 0a 0a 53 61 74 2c 20 32 36 20 4d 61 72 20 32 30 31 31 20 30 30 3a 34 33 3a 33 36 20 2b 30 30 30 30 0a 78 2d 61 6d 7a 2d 61 63 6c 3a 70 75 62 6c 69 63 2d 72 65 61 64 0a 2f 6d 6c 68 2d 70 72 6f 64 75 63 74 69 6f 6e 2f 31 2d 31 33 32 2d 31 33 30 31 30 34 37 32 30 30 2d 31 2e 6a 70 67A7CB0311812CD721ZUY0mH4Q20Izgt / 9BNhpJl9OoOCp59DKxlH2JJ6K + sksyxI8lFtmJrJOk1imxM / AGmgRObHEFuirWPwaqRgdKiQK / EQ = PUT sáb, 26 mar 2011 00:43:36 +0000 x-amz-acl: public-read /bucket/1-132-1301047200-1.jpg-removed por seguridad- 0
pero al enviar solicitudes formateadas correctamente, dice que no estoy autenticado:
Consulta utilizada:
PUT /1-132-1301047200-1.jpg Host HTTP / 1.1: bucket.s3.amazonaws.com Fecha: sáb, 26 de marzo de 2011 00:41:50 +0000 x-amz-copy-source: / bucket / clock. jpg x-amz-acl: autorización de lectura pública: AWS -removó para seguridad-: BMiGhgbFnVAJyiderKjn1cT7cj4 =
HTTP / 1.1 403 prohibido
x-amz-request-id: ABE45FD4DFD19927
x-amz-id-2: CnkMmoF550H1zBlrwwKfN8zoOSt7r / zud8mRuLqzzBrdGguotcvrpZ3aU4HR4RoO
Tipo de contenido: application / xml
Transferencia de codificación: fragmentada
Fecha: sáb, 26 de marzo de 2011 00:41:50 GMT
Servidor: AmazonS3
Acceso denegado
Los usuarios anónimos no pueden copiar objetos. Por favor autentica
ABE45FD4DFD19927CnkMmoF550H1zBlrwwKfN8zoOSt7r / zud8mRuLqzzBrdGguotcvrpZ3aU4HR4RoO 0
Fecha: sáb, 26 de marzo de 2011 00:41:50 GMT
Conexión: cerrar
Servidor: AmazonS3
He intentado durante semanas formatear correctamente una solicitud de REST para la API de Amazon AWS S3 utilizando los ejemplos disponibles en la web
¿Has probado Amazon AWS SDK para PHP ? Es completo, completo y, lo más importante, escrito por Amazon. Si su propio código no funciona para usted, algo va a estar realmente mal.
Aquí hay un código de ejemplo que usa el SDK vinculado para cargar example.txt
en el directorio actual a un depósito llamado ''my_very_first_bucket''.
<?php
// Complain wildly.
ini_set(''display_errors'', true);
error_reporting(-1);
// Set these yourself.
define(''AWS_KEY'', '''');
define(''AWS_SECRET_KEY'', '''');
// We''ll assume that the SDK is in our current directory
include_once ''sdk-1.3.1/sdk.class.php'';
include_once ''sdk-1.3.1/services/s3.class.php'';
// Set the bucket and name of the file we''re sending.
// It happens that we''re actually uploading the file and
// keeping the name, so we''re re-using the variable
// below.
$bucket_name = ''my_very_first_bucket'';
$file_to_upload = ''example.txt'';
// Fire up the object
$s3 = new AmazonS3(AWS_KEY, AWS_SECRET_KEY);
// This returns a "CFResponse"
$r = $s3->create_object(
$bucket_name,
$file_to_upload,
array(
// Filename of the thing we''re uploading
''fileUpload'' => (__DIR__ . ''/'' . $file_to_upload),
// ACL''d public.
''acl'' => AmazonS3::ACL_PUBLIC,
// No wai.
''contentType'' => ''text/plain'',
// The docs say it''ll guess this, but may as well.
''length'' => filesize(__DIR__ . ''/'' . $file_to_upload)
)
);
// Did it work?
echo "Worked: ";
var_dump($r->isOK());
// Status as in HTTP.
echo "/nStatus: ";
var_dump($r->status);
// The public URL by which we can reach this object.
echo "/nURL: ";
echo $s3->get_object_url($bucket_name, $file_to_upload);
// Tada!
echo "/n";
Documentos API apropiados:
-
get_object_url
-
create_object
- La clase
CFResponse
.
Puede navegar el resto de los métodos en el menú de la izquierda. Es bastante completo, incluida la creación, gestión, borrado, lo mismo para objetos, etc.
Debería poder dejar esto en su código y hacer que funcione correctamente. PHP 5.2-seguro.
Editar por Silver Tiger:
Charles -
El método que proporciona es el uso de las funciones de API SDK para cargar un archivo desde el sistema de archivos local a un cubo de mi elección. Tengo esa parte que ya funciona a través de Flex y carga como un encanto. El problema en cuestión es poder enviar una solicitud REST a AWS S3 para cambiar el nombre del archivo de su nombre actual "cargado", a un nuevo nombre con el nombre más adecuado que funcione con mi back-end (base de datos, seguimiento, etc., que manejar y visualizar por separado en PHP con MyySQL).
AWS S3 no es realmente compatible con una función de "copia", por lo que proporcionan un método para volver a "PONER" un archivo leyendo el origen de su propio depósito y colocando una copia nueva con un nombre diferente en el mismo contenedor. La dificultad que he tenido es procesar la solicitud REST, de ahí el cifrado HMAC.
Agradezco mucho su tiempo y entiendo el ejemplo que me ha proporcionado, ya que también tengo una copia de trabajo de la carga de PHP que estaba funcionando antes de diseñar la aplicación Flex. El motivo de Flex fue habilitar actualizaciones de estado y una barra de progreso actualizada dinámicamente, que también funciona como un encanto :).
Continuaré persiguiendo una solución REST desde la perspectiva de Amason zupport, será la única forma en que puedo cambiar el nombre de un archivo que ya existe en mi cubo por su equipo de soporte.
Como siempre, si tiene sugerencias o sugerencias sobre el envío de REST, le agradecería cualquier comentario.
Gracias,
Tigre plateado
Copia / eliminación de la prueba funciona:
$r = $s3->copy_object(
array( ''bucket'' => $bucket_name, ''filename'' => $file_to_upload ),
array( ''bucket'' => $bucket_name, ''filename'' => ''foo.txt'' )
);
// Did it work?
echo "Worked: ";
var_dump($r->isOK());
// Status as in HTTP.
echo "/nStatus: ";
var_dump($r->status);
// The public URL by which we can reach this object.
echo "/nURL: ";
echo $s3->get_object_url($bucket_name, ''foo.txt'');
echo "/nDelete: ";
// Nuke?
$r = $s3->delete_object($bucket_name, $file_to_upload);
// Did it work?
echo "Worked: ";
var_dump($r->isOK());
// Status as in HTTP.
echo "/nStatus: ";
var_dump($r->status);
Editar por Silver Tiger:
Charles -
No se necesita REST, no molesta ... SDK 1.3.1 y su ayuda resolvió el problema. el código que usé para probar se parece mucho al tuyo:
// Complain wildly.
ini_set(''display_errors'', true);
error_reporting(-1);
// Set these yourself.
define(''AWS_KEY'', ''removed for security'');
define(''AWS_SECRET_KEY'', ''removed for security'');
// We''ll assume that the SDK is in our current directory
include_once ''includes/sdk-1.3.1/sdk.class.php'';
include_once ''includes/sdk-1.3.1/services/s3.class.php'';
// Set the bucket and name of the file we''re sending.
// It happens that we''re actually uploading the file and
// keeping the name, so we''re re-using the variable
// below.
$bucket = ''bucket'';
$file_to_upload = ''example.txt'';
$Source_file_to_copy = ''Album.jpg'';
$Destination_file = ''Album2.jpg'';
// Fire up the object
// Instantiate the class
$s3 = new AmazonS3();
$response = $s3->copy_object(
array( // Source
''bucket'' => $bucket,
''filename'' => $Source_file_to_copy
),
array( // Destination
''bucket'' => $bucket,
''filename'' => $Destination_file
)
);
// Success?
var_dump($response->isOK());
Ahora implementaré la eliminación después de la copia, y estamos dorados. Gracias señor por su visión y ayuda.
Tigre plateado