PHP on Azure: how to list blobs in a 'folder' - php

I'm trying to list all blobs contained in the 'accidentsPhoto' 'folder' located at the root of the blob container:
// List blobs.
$key = 'accidentsPhoto';
$blobListOptions = new ListBlobsOptions();
$blobListOptions->setPrefix($key);
$blobListOptions->setDelimiter("/");
$blobList = $blobRestProxy->listBlobs($blobContainer, $blobListOptions);
foreach($blobList->getBlobPrefixes() as $key => $blob) {
echo "BlobPrefix ".$key.": \t".$blob->getName()."\n";
}
foreach($blobList->getBlobs() as $key => $blob) {
echo "Blob ".$key.": \t".$blob->getName()."\t(".$blob->getUrl().")\n";
}
Alas, only the key is listed as follows:
Set-Cookie: XXXX
Date: Tue, 15 Aug 2017 12:42:28 GMT
Connection: keep-alive
BlobPrefix 0: accidentsPhoto/

You'll need to remove the following line to list blobs.
$blobListOptions->setDelimiter("/");

Related

Fetch personid from text string

I am getting below response from apparel21 api for create person.
HTTP/1.1 201 Created
Cache-Control: private
Location: https://domainName.com.au:8181/retailapi_test/Persons//15668?countryCode=AU
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 10 Aug 2015 07:11:38 GMT
Content-Length: 0
Is there any way using which I can only retrieve person id (15668) form above text ??
Can any one please help.
PHP code:
$hdr_array = http_parse_headers($header);
$str = $hdr_array['Location'];
//$str = 'https://domainName.com.au:8181/retailapi_test/Persons//15668?countryCode=AU';
echo getStringBetween($str , 'Persons//', '?countryCode');
function getStringBetween($str,$from,$to)
{
$sub = substr($str, strpos($str,$from)+strlen($from),strlen($str));
return substr($sub,0,strpos($sub,$to));
}
using these two answers -
https://stackoverflow.com/a/30084266/2857264
https://stackoverflow.com/a/18680847/2857264
You can use parse_url function to explode URL.
Try
$hdr_array = http_parse_headers($header);
$string = $hdr_array['Location'];
//$string = "https://domainName.com.au:8181/retailapi_test/Persons//15668?countryCode=AU";
$personID = parse_url($string, PHP_URL_PATH);
$personID = str_ireplace('/retailapi_test/Persons//', '', $personID);
echo $personID;
Another take on the problem, using preg_split and preg_match etc
$headerlist="
HTTP/1.1 201 Created
Cache-Control: private
Location: https://domainName.com.au:8181/retailapi_test/Persons//15668?countryCode=AU
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 10 Aug 2015 07:11:38 GMT
Content-Length: 0";
$location=false;
$pieces=array_filter( preg_split( '#\n#', $headerlist ) );
foreach( $pieces as $pair ) {
list( $param, $value )=preg_split( '#:\s#',$pair );
if( strtolower( trim($param) )=='location' ){
$location=$value;
break;
}
}
$path=parse_url( $location, PHP_URL_PATH );
preg_match('#\d+#',$path,$matches);
$userid=$matches[0];
echo 'userid:'.$userid;

fine-uploader can't read iframe response with IE7

I'm using the jquery.fineuploader-3.7.0 and Code igniter framework for the server side.
My js code :
$('#manual-fine-uploader').fineUploader({
request : { endpoint: 'declaration/uploadfile'},
autoUpload : false,
template : '<div class="qq-uploader span12">' +
' <pre class="qq-upload-drop-area span12"><span>{dragZoneText}</span></pre>' +
' <div class="qq-upload-button " style="width: auto;">{uploadButtonText}</div>' +
' <span class="qq-drop-processing"><span>{dropProcessingText}</span><span class="qq-drop-processing-spinner"></span></span>' +
' <ul id="qq-upload-list" class="qq-upload-list" style="margin-top:10px; text-align:center;"><li></li></ul>' +
' <ul class="qq-upload-list" style="margin-top: 10px; text-align: center;"></ul>' +
'</div>',
fileTemplate : '<li>' +
' <div class="qq-progress-bar"></div>' +
' <span class="qq-upload-spinner"></span>' +
' <span class="qq-upload-finished"></span>' +
' <span class="qq-upload-file"></span>' +
' <span class="qq-upload-size"></span>' +
' <a class="qq-upload-cancel" href="#">{cancelButtonText}</a>' +
' <a class="qq-upload-retry" href="#">{retryButtonText}</a>' +
' <a class="qq-upload-delete" href="#">{deleteButtonText}</a>' +
' <span class="qq-upload-status-text">{statusText}</span>' +
'</li>',
failedUploadTextDisplay : {
mode : 'custom',
maxChars : 1500,
responseProperty : 'error',
enableTooltip : true
},
text : {
uploadButton : '<color=#2E6E9E><b>Selectionnez le fichier à déposer</b></color>',
failUpload : 'Le chargement a échoué'
} });
$('#triggerUpload').click(function() {
$('#manual-fine-uploader').fineUploader('setParams', {'id_fait':$('#id_fait').attr('value') });
$('#manual-fine-uploader').fineUploader('uploadStoredFiles'); });
My server side response are :
>HTTP/1.0 200 OK
>Date: Fri, 26 Jul 2013 08:12:09 GMT
>Server: Apache/2.2.15 (CentOS)
>X-Powered-By: PHP/5.3.3
>Expires: Thu, 19 Nov 1981 08:52:00 GMT
>Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
>Pragma: no-cache
>Connection: close
>Content-Type: text/html; charset=UTF-8
content :
{"success":true,"file_inner":"<a href='pj\/'116810_116810_cimpa_insertion.xls' target='_blank'>116810_cimpa_insertion.xls<\/a>"}
Under FF, Chrome i have a sucess message on my web page (the green)
but under IE7 or IE8 i have a message who said in my debug bar console:
[FineUploader 3.7.0] Error when attempting to parse iframe upload response ([object Error])
[FineUploader 3.7.0] 'error' is not a valid property on the server response.
and web page error message(the red ).
But the upload are ok (the file are correctly on my server)
I'm a beginner under fine-uploader, could you help me to find where i have make an error please ?
code of the server side:
/**
* uploadfile
* #access public
* #return string
*/
public function uploadfile() {
$post['id_fait'] = $this->input->post('id_fait');
if ( empty($post['id_fait']) ) {
$return['error'] = 'ID_FAIT manquant';
return true;
}
else {
$_FILES['qqfile']['name'] = $post['id_fait']."_".$_FILES['qqfile']['name'];
$config['upload_path'] = DOCUMENT_PATH;
$config['max_size'] = UPLOAD_MAX_SIZE;
$config['overwrite'] = FALSE;
$config['allowed_types'] = ALLOWED_EXT;
$config['remove_spaces'] = FALSE;
$this->load->library('upload', $config);
if ( !$this->upload->do_upload('qqfile')) { $return['error'] = $this->upload->error_msg[0]; }
else {
$data = $this->upload->data();
$post['fichier'] = $data['file_name'];
$insert = $this->db->insert('senla_faits_piece_jointe',$post);
$return['success'] = $insert;
$return['file_inner'] = "<a href='pj/'".$post['id_fait']."_".$data['file_name']."' target='_blank'>".$data['file_name']."</a>";
}
}
echo json_encode( $return, JSON_FORCE_OBJECT );
}
UPDATE :
After i make the change my server response :
HTTP/1.0 200 OK
Date: Fri, 26 Jul 2013 20:21:01 GMT
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.3.3
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 124
Connection: close
Content-Type: text/html; charset=UTF-8
and the content :
{"success":true,"file_inner":"<a href=\"pj\/116842_116842_brochure 12.pdf\" target=\"_blank\">116842_brochure 12.pdf<\/a>"}
I have always a red web message who said : upload fail (in french) and this message in my debug bar console :
[FineUploader 3.7.0] Error when attempting to parse iframe upload response ([object Error])
[FineUploader 3.7.0] 'error' is not a valid property on the server response.
Thank a lot for your help
Stéphane
Update 2 after change the content type, always the same problem :
The server response :
HTTP/1.0 200 OK
Date: Sat, 27 Jul 2013 20:14:38 GMT
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.3.3
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: PHPSESSID=7riosh2q9edldanjp9vtg4ili3; path=/
Set-Cookie: PHPSESSID=7riosh2q9edldanjp9vtg4ili3; path=/
Connection: close
Content-Type: text/plain; charset=UTF-8
The content :
{"success":true,"file_inner":"<a href=\"pj\/116841_116841_capture_portail_sonacotra.doc\" target=\"_blank\">116841_capture_portail_sonacotra.doc<\/a>"}
I think it's not a problem of content, perhaps it's a problem of IE who can't read the response send by the server across the iframe, but i don't know sufficiently the javascript to find the solution
UPDATE 29/07/2013 :
I have make a test :
If i delete my $return['file_inner']
And i keep only the sucess or error message then that's ok
My $return['file_inner'] are just here because user could be verify the document upload by clicking on the link. But it's not a very important fonction, i could delete it.
Perhaps i have forget something when they are severals attributes in my object "response". or perhaps fine uploader code wait only one attribut.
After having a closer look, there are a few odd properties of your JSON response.
I have very little professional experience with PHP, but I can say that your response content is not correct. You should probably be using json_encode to format your response content. Fine Uploader has an example PHP script that already does this. Perhaps you should have a look.
Either way, your response content should look like this:
{"success":"true","file_inner":"116841_capture_portail_sonacotra.doc"}
Solution by OP.
The solution are in the example php script, my error are to make a url in my object without the htmlspecialchars conversion. With this php code on the server side it's OK
/**
* uploadfile
* #access public
* #return string
*/
public function uploadfile() {
$post['id_fait'] = $this->input->post('id_fait');
if ( empty($post['id_fait']) ) {
$return['error'] = 'ID_FAIT manquant';
return true;
}
else {
$_FILES['qqfile']['name'] = $post['id_fait']."_".$_FILES['qqfile']['name'];
$config['upload_path'] = DOCUMENT_PATH;
$config['max_size'] = UPLOAD_MAX_SIZE;
$config['overwrite'] = FALSE;
$config['allowed_types'] = ALLOWED_EXT;
$config['remove_spaces'] = FALSE;
$this->load->library('upload', $config);
if ( !$this->upload->do_upload('qqfile')) { $return['error'] = $this->upload->error_msg[0]; }
else {
$data = $this->upload->data();
$post['fichier'] = $data['file_name'];
$insert = $this->db->insert('senla_faits_piece_jointe',$post);
$return['success'] = $insert;
$return['file_inner'] = "".$data['file_name']."";
}
}
// log_askel($this->upload);
header('Content-type: text/plain');
echo htmlspecialchars(json_encode($return), ENT_NOQUOTES);
}

php picasa api show large image

Ok so far I have been able to show thumbnails from user/album using the google feed. Everything displays ok, except when I want to show the thumbnail image larger. I can't seem to get the large image to show, not sure what to use here..here's my code:
<?php
$user = '100483307985144997386';
$albumid = '5092093264124561713';
$picasaURL = "http://picasaweb.google.com/$user/";
$albumfeedURL = "http://picasaweb.google.com/data/feed/api/user/$user/albumid/$albumid";
$sxml_album = simplexml_load_file($albumfeedURL);
echo '<table cellpadding="3" cellspacing="3">';
echo "<tr>";
$i = 0;
foreach( $sxml_album->entry as $album_photo )
{
//$title = $album_photo->title;
$summary = $album_photo->summary;
// Write thumbnail to file
$media = $album_photo->children('http://search.yahoo.com/mrss/');
$thumbnail = $media->group->thumbnail[1];
$gphoto = $album_photo->children('http://schemas.google.com/photos/2007/');
$linkName = $gphoto->group->attributes()->{'url'};
// Direct address to thumbnail
$thumbAddy = $thumbnail->attributes()->{'url'};
if($i%4==0) { echo '</tr><tr>'; }
echo '<td style="width:90px; overflow:hidden; word-wrap:break-word; font-size:12px;">';
echo '<a class="fancybox-buttons" data-fancybox-group="button" href="'. $linkName . '"><img src="'. $thumbAddy . '" /></a>';
echo '<p>'. $summary . '</p></td>';
$i++;
}
echo '</tr></table>';
the feed/api for each photo contains 3 thumbs and a large picture which are accessible on the native http rest api in the following:
"media$thumbnail":[
{
"url":"https://lh3.googleusercontent.com/-_FFMNGPU1TQ/TtukXyN4eCI/AAAAAAAACso/EzPmut2iKVQ/s72/DSC01612.JPG",
"height":72,
"width":48
},
{
"url":"https://lh3.googleusercontent.com/-_FFMNGPU1TQ/TtukXyN4eCI/AAAAAAAACso/EzPmut2iKVQ/s144/DSC01612.JPG",
"height":144,
"width":96
},
{
"url":"https://lh3.googleusercontent.com/-_FFMNGPU1TQ/TtukXyN4eCI/AAAAAAAACso/EzPmut2iKVQ/s288/DSC01612.JPG",
"height":288,
"width":192
}
],
LARGE ONE:
"media$group":{
"media$content":[
{
"url":"https://lh3.googleusercontent.com/-_FFMNGPU1TQ/TtukXyN4eCI/AAAAAAAACso/EzPmut2iKVQ/DSC01612.JPG",
"height":512,
"width":341,
"type":"image/jpeg",
"medium":"image"
}
similar reference
When coding clients to an underlying REST api it can often help to have a good grasp on the native protocol and what character streams ( request / response ) are on the wire. Then you adapt PHP/Curl to what is there in http protocol.
The google oauth playground is a great tool for testing the back and forth dialogs involved in development against any of the gdata apis ( including picasa )...
playground
here is the playground request code to get the thumbs and the large pic for a given album/photo...
GET //data/entry/api/user/rowntreerob/albumid/5682316071017984417/photoid/5682316083381958690?fields=media%3Agroup%2Fmedia%3Athumbnail%5B%40url%5D%2Cmedia%3Agroup%2Fmedia%3Acontent%5B%40url%5D&alt=json HTTP/1.1
Host: picasaweb.google.com
Authorization: OAuth ya29.AHES6ZT123y3Y5Cy3rILYg4Ah4q....
HTTP/1.1 200 OK
status: 200
gdata-version: 1.0
content-length: 756
x-xss-protection: 1; mode=block
content-location: https://picasaweb.google.com//data/entry/api/user/rowntreerob/albumid/5682316071017984417/photoid/5682316083381958690?fields=media%3Agroup%2Fmedia%3Athumbnail%5B%40url%5D%2Cmedia%3Agroup%2Fmedia%3Acontent%5B%40url%5D&alt=json
x-content-type-options: nosniff
set-cookie: _rtok=a1p2m3PiHFkc; Path=/; Secure; HttpOnly, S=photos_html=sX3EHuLxGEre_OMvR0LTPg; Domain=.google.com; Path=/; Secure; HttpOnly
expires: Wed, 16 May 2012 03:23:51 GMT
vary: Accept, X-GData-Authorization, GData-Version, Cookie
x-google-cache-control: remote-fetch
-content-encoding: gzip
server: GSE
last-modified: Fri, 06 Jan 2012 17:57:33 GMT
via: HTTP/1.1 GWA
cache-control: private, max-age=0, must-revalidate, no-transform
date: Wed, 16 May 2012 03:23:51 GMT
access-control-allow-origin: *
content-type: application/json; charset=UTF-8
x-frame-options: SAMEORIGIN
and the response to the above run thru a prettyprint...
"version":"1.0",
"encoding":"UTF-8",
"entry":{
"xmlns":"http://www.w3.org/2005/Atom",
"xmlns$media":"http://search.yahoo.com/mrss/",
"media$group":{
"media$content":[
{
"url":"https://lh3.googleusercontent.com/-_FFMNGPU1TQ/TtukXyN4eCI/AAAAAAAACso/EzPmut2iKVQ/DSC01612.JPG",
"height":512,
"width":341,
"type":"image/jpeg",
"medium":"image"
}
],
"media$thumbnail":[
{
"url":"https://lh3.googleusercontent.com/-_FFMNGPU1TQ/TtukXyN4eCI/AAAAAAAACso/EzPmut2iKVQ/s72/DSC01612.JPG",
"height":72,
"width":48
},
{
"url":"https://lh3.googleusercontent.com/-_FFMNGPU1TQ/TtukXyN4eCI/AAAAAAAACso/EzPmut2iKVQ/s144/DSC01612.JPG",
"height":144,
"width":96
},
{
"url":"https://lh3.googleusercontent.com/-_FFMNGPU1TQ/TtukXyN4eCI/AAAAAAAACso/EzPmut2iKVQ/s288/DSC01612.JPG",
"height":288,
"width":192
You can specify the size by using imgmax parameter (imgmax=d means original image).
https://developers.google.com/picasa-web/docs/2.0/reference#Parameters
Have you tried a print_r( $album_photo ) to check the exact format of the object and what it contains?
I'm pretty sure that there are a bunch of other parameters you can specify in that API to get access to different sizes of pictures and thumbnails. Check the docs.
I've accessed this API using json-script format a while ago and from memory there are a lot of options you can specify.
I have scoured the entire internet trying to find an answer to this problem. Nobody actually answered the question. For future reference to anyone else reading, or my future self, to get the large image do this:
echo $album_photo->content->attributes()->{'src'};
That was WAAAAYY more complicated than it should have been, and the normal XML user probably would have already known how to do that. :/

PHP script piping email parse

I'm doing this piping php script that fetch the arriving emails and the parse it and show it. I used this tutorial: http://www.damnsemicolon.com/php/parse-emails-in-php-with-email-piping-part-1 (and the following ones), I tried it with a standard email that I had sent to my server and it did work well, but then i tried another and I got a lot of errors. I used the print_r($decoded); to show me all of the different parts of the email and instead of getting a fully parse email, all the content of the emails goes to the $decode[0]['body]; Why is this happening? (I will not post the code cause it's the same as the tutorials)
print_r($decode)= Array (
[0] => Array (
[Headers] => Array ( )
[Parts] => Array ( )
[Position] => 0
[Body] => From jtferreira#teste.local Thu Apr 26 12:33:44 2012 Received: from [192.168.1.92] by ubuntuserver.lan with esmtp (Exim 4.76) (envelope-from ) id 1SNMxE-0000VB-TR for jtferreira#teste.local; Thu, 26 Apr 2012 12:33:44 +0100 Message-ID: <4F993299.8040605#teste.local> Date: Thu, 26 Apr 2012 12:33:45 +0100 From: =?ISO-8859-1?Q?=22Jo=E3o_Ferreira_=28m=E1quina_virtual=29=22?= User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:11.0) Gecko/20120327 Thunderbird/11.0.1 MIME-Version: 1.0 To: jtferreira#teste.local Subject: Sample Email Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit It's the same?
[BodyPart] => 1
[BodyLength] => 744
)
)
Thanks.
As Mario said, the problem was with the UTF 8-BOM. If anyone have this problem, I recomend you to use this code:
<?php
// substitua pelo caminho para o arquivo que deseja limpar
$file = "C:/wamp/www/wordpress/wp-content/themes/basic-gray/lib/langs.php";
print removeUTF8BOM($file) ? 'BOM removido!' : 'Não havia BOM a ser removido...';
function removeUTF8BOM($fil) {
$newcontent = '';
$first = false;
$fh = fopen($fil, 'r');
while($part = fread($fh, 1024)) {
if(!$first) {
if(preg_match('/^\xEF\xBB\xBF/', $part)) {
$newcontent = preg_replace('/^\xEF\xBB\xBF/', "", $part);
} else {
fclose($fh);
return false;
}
$first = true;
} else $newcontent .= $part;
}
fclose($fh);
$fh = fopen($fil, 'w');
fwrite($fh, $newcontent);
fclose($fh);
return true;
}
?>
(http://www.caugb.com.br/2009/07/remover-o-bom-de-arquivos-em-utf-8/)

PUT/Copy With PHP, REST, Flex, and Amazon S3

I have been trying for weeks to properly format a REST request to the Amazon AWS S3 API using the available examples on the web but have been unable to even successfully connect.
I have found the code to generate a signature, found the proper method for formatting the "string to encode", and the http headers. I have worked my way through the signatureDoesNotMatch errors just to get a Anonymous users can not perform copy functions, Please authenticate message.
I have a working copy of an Adobe Flex application that successfully uploads files, but with their "original" file name. The point of using the REST with the Amazon API is to perform a PUT (copy) of the file, just so I can rename it to something my back end system can use.
If I could find a way to get this REST submission to work, or perhaps a way to specify a "new" filename within Flex while uploading I could avoid this whole REST situation all together.
If anyone has successfully performed a PUT/Copy command on the Amazon API via REST I would be very interested in how this was accomplished - OR - if anyone has been able to change the destination file name using the Flex fileReference.browse() method I would also be eternally grateful for any pointers.
PHP code for this is as follows:
$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
When I submit a malformed or incorrect header I get the corresponding error message as expected:
Query:
PUT /bucket/1-132-1301047200-1.jpg HTTP/1.1 Host: s3.amazonaws.com x-amz-acl: public-read Connection: keep-alive Content-Length: 34102 Date: Sat, 26 Mar 2011 00:43:36 +0000 Authorization: AWS -removed for security-:GmgRObHEFuirWPwaqRgdKiQK/EQ=
HTTP/1.1 403 Forbidden
x-amz-request-id: A7CB0311812CD721
x-amz-id-2: ZUY0mH4Q20Izgt/9BNhpJl9OoOCp59DKxlH2JJ6K+sksyxI8lFtmJrJOk1imxM/A
Content-Type: application/xml
Transfer-Encoding: chunked
Date: Sat, 26 Mar 2011 00:43:36 GMT
Connection: close
Server: AmazonS3
397 SignatureDoesNotMatchThe request signature we calculated does not match the signature you provided. Check your key and signing method.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 Sat, 26 Mar 2011 00:43:36 +0000 x-amz-acl:public-read /bucket/1-132-1301047200-1.jpg-removed for security- 0
but when sending properly formatted requests, it says I'm not authenticated:
Query being used:
PUT /1-132-1301047200-1.jpg HTTP/1.1 Host: bucket.s3.amazonaws.com Date: Sat, 26 Mar 2011 00:41:50 +0000 x-amz-copy-source: /bucket/clock.jpg x-amz-acl: public-read Authorization: AWS -removed for security-:BMiGhgbFnVAJyiderKjn1cT7cj4=
HTTP/1.1 403 Forbidden
x-amz-request-id: ABE45FD4DFD19927
x-amz-id-2: CnkMmoF550H1zBlrwwKfN8zoOSt7r/zud8mRuLqzzBrdGguotcvrpZ3aU4HR4RoO
Content-Type: application/xml
Transfer-Encoding: chunked
Date: Sat, 26 Mar 2011 00:41:50 GMT
Server: AmazonS3
AccessDenied
Anonymous users cannot copy objects. Please authenticate
ABE45FD4DFD19927CnkMmoF550H1zBlrwwKfN8zoOSt7r/zud8mRuLqzzBrdGguotcvrpZ3aU4HR4RoO 0
Date: Sat, 26 Mar 2011 00:41:50 GMT
Connection: close
Server: AmazonS3
I have been trying for weeks to properly format a REST request to the Amazon AWS S3 API using the available examples on the web
Have you tried the Amazon AWS SDK for PHP? It's comprehensive, complete, and most importantly, written by Amazon. If their own code isn't working for you, something's gonna be really wrong.
Here is example code using the linked SDK to upload example.txt in the current directory to a bucket named '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";
Appropriate API docs:
get_object_url
create_object
The CFResponse class.
You can navigate the rest of the methods in the left menu. It's pretty comprehensive, including new bucket creation, management, deletion, same for objects, etc.
You should be able to basically drop this in to your code and have it work properly. PHP 5.2-safe.
Edit by Silver Tiger:
Charles -
The method you provide is using the API SDK functions to upload a file from the local file system to a bucket of my choosing. I have that part working already via Flex and uploads work like a charm. The problem in question is being able to submit a REST request to AWS S3 to change the file name from it's current "uploaded" name, to a new name more suited name that will work with my back end (database, tracking etc, which I handle and display seperately in PHP with MyySQL).
AWS S3 does not truly support a "copy" function, so they provided a method to re-"PUT" a file by reading the source from your own bucket and placing a new copy with a different name in the same bucket. The difficulty I have been having is processing the REST request, hence the HMAC encryption.
I do appreciate your time and understand the example you have provided as i also have a working copy of the PHP upload that was functioning before I designed the Flex application. The reason for the Flex was to enable status updates and a dynamically updated progress bar, which is also working like a charm :).
I will continue to persue a REST solution as from the perspective of Amason zupport, it will be the only way i can rename a file already existing in my bucket per thier support team.
As always, if you have input or suggestions regarding the REST submission I would be greatful for any feedback.
Thanks,
Silver Tiger
Proof copy/delete works:
$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);
Edit by Silver Tiger:
Charles -
No REST needed, no bothers ... SDK 1.3.1 and your help solved the issue. the code I used to test looks a lot like yours :
// 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());
Now I will implement the delete after the copy, and we're golden. Thank you sir for your insight and help.
Silver Tiger

Categories