2012-04-17 24 views
6

Questo è andato in giro un certo numero di volte, ma sono ancora un po 'disorientato. Molte risposte si limitano a parlare delle barre di avanzamento del caricamento e non del progresso effettivo del caricamento da un caricamento S3.PHP upload S3 upload

Ho letto un numero di domande e ho trovato un certo numero di pezzi software ma non sono ancora più vicino alla comprensione della questione fondamentale degli upload S3.

C'è un modo di caricare su S3 mentre si capisce il progresso di quel caricamento senza dover utilizzare le risorse del proprio server app per archiviare il file nella directory temporanea prima?

Devo prima memorizzare il file sul mio server e poi passare a S3? Ho sentito persone parlare di streaming bit alla volta per S3 (un blocco alla volta), ma non sono sicuro di ciò che questo comporta. Immaginavo che stavo caricando dal lato client in una pagina HTML come potrei fare lo streaming del pezzo di chunk da una parte in più da come viene? (Non vedo alcun esempio di questo solo un esempio di quando il file è già presente nel tuo sistema e conosci i blocchi che sono un po 'inutili tbh).

C'è ovviamente un esempio di avanzamento del caricamento nei documenti API, ma di nuovo si presume che il file sia sul server per primo e non provenga da un altro computer fornito dall'utente.

EDIT: Il mio pensiero originale era quello di creare uno script PHP in grado di eseguire il ping di AWS una volta ogni volta che veniva caricato il caricamento. Sto guardando attraverso l'API per vedere se supportano qualcosa di simile, ma non ho fortuna. Fatemi sapere se c'è qualcosa ...

Ulteriori EDIT: Flash è l'unico modo per andare con questo?

Grazie,

risposta

3

SI, è possibile in AWS PHP SDK v3.

$client = new S3Client(/* config */); 

$result = $client->putObject([ 
    'Bucket'  => 'bucket-name', 
    'Key'  => 'bucket-name/file.ext', 
    'SourceFile' => 'local-file.ext', 
    'ContentType' => 'application/pdf', 
    '@http' => [ 
     'progress' => function ($downloadTotalSize, $downloadSizeSoFar, $uploadTotalSize, $uploadSizeSoFar) { 
      printf(
       "%s of %s downloaded, %s of %s uploaded.\n", 
       $downloadSizeSoFar, 
       $downloadTotalSize, 
       $uploadSizeSoFar, 
       $uploadTotalSize 
      ); 
     } 
    ] 
]); 

Questo è spiegato nei documenti AWS - S3 Config section. Funziona esponendo la proprietà progress di GuzzleHttp richiamabile, come spiegato in this SO answer.

0

Dopo un sacco di ricerca in giro ho trovato la risposta semplice a questa domanda è no.

Fondamentalmente il modo migliore per farlo, come ho scoperto dalla codifica di Amazons (il loro piccolo widget di caricamento sulla console di AWS S3), è davvero possibile ottenere il progresso del caricamento inviando prima a un altro server quale PHP può leggi per informazioni sull'avanzamento.

Questo crea una politica 'pass-through' utilizzando i propri server delle app/directory tmp come trampolino di lancio. Questo sembra essere il metodo preferito.

+0

Hai ancora qualche esempio disponibile? Probabilmente dovrò fare una cosa simile .. – trainoasis

+0

Solo codice molto vecchio che non penso sia valido con la loro nuova API, in pratica si carica come di consueto nel nostro server e quindi si copia nella sua forma completa o per chunk in S3 (utilizzando un modulo a più parti è possibile ottenere i blocchi prima che sia completamente caricato in PHP dal flusso) – Sammaye

+0

Ok grazie, lo faremo quindi .. – trainoasis

0

AWS PHP SDK ha un esempio di codice in cui mostrano il progresso del caricamento durante il caricamento su S3. Non sono sicuro che sia valido per file di piccole dimensioni, ma per lo streaming funziona sicuramente.

È possibile controllare più da presso - http://aws.amazon.com/sdkforphp/

In un certo senso, se stanno mostrando i progressi - siamo sicuramente in grado di ottenere che nella forma di una barra di avanzamento con l'aiuto di un framework JavaScript come jQuery ecc

Ci lavorerò molto presto e pubblicherò sicuramente un tutorial. Saluti!

+0

Mi piacerebbe molto, questa domanda è stata scritta circa 4 versioni fa del sdk quindi sarei molto interessato se le cose sono cambiate e AWS ha un buon modo di dong questo – Sammaye

+1

Sarebbe meglio se si potesse collegare alla pagina specifica con l'esempio di codice e non solo la homepage di sdk. –

+0

Hai pubblicato un tutorial su questo? – trainoasis

0

Sì, è possibile tramite il caricamento multipart: http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMPphpAPI.html

caricando multipart è un processo in tre fasi: Si avvia il caricamento, di caricare i pezzi di oggetti, e dopo aver caricato tutte le parti, si completa il caricamento multipart . Dopo aver ricevuto la richiesta di caricamento multipart completa, Amazon S3 costruisce l'oggetto dalle parti caricate e puoi quindi accedere all'oggetto esattamente come faresti con qualsiasi altro oggetto nel tuo bucket.

http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuoverview.html

che cercherò di fare questo personalmente molto presto, ma questo è ciò che serve per iniziare.

+0

Devi ancora caricarlo sul tuo server per capire una progressione dal momento che devi avere la dimensione totale del file sul tuo server prima di poter fare qualcosa con esso. Effettivamente, lo caricherete sul tuo sertver prima come caricamento normale e poi multiparte su Amazon per ottenere la progressione del caricamento, il che significa che in effetti starete valutando la progressione del caricamento sul vostro server. Suppongo che potresti riscrivere gli script PHP di base per rilasciare parti di upload che puoi poi caricare su Amazon, ma il core PHP attualmente non fa questo – Sammaye

+0

@Sammaye Sono veramente nel mezzo di fare questo atm e sto dovendo carica sul server poi su S3. Fino a quando non capisco di andare direttamente a S3 stavo andando a scrivere un piccolo trucco o scrivere temporaneamente su un file per inviare feedback ai miei utenti. Finché puoi vedere o utilizzare questa funzione multipart dovresti essere in grado di connettersi, in un modo o nell'altro. –

+1

@ MichaelCalkins hai mai ottenuto questo risultato? Il 2014 è quasi finito e non riesco ancora a vedere una risposta chiara per fare questo? – turntwo

-2

Sì, è possibile farlo modificando s3.php come questo,

<?php 
class S3Withprogressbar { 
// ACL flags 
const ACL_PRIVATE = 'private'; 
const ACL_PUBLIC_READ = 'public-read'; 
const ACL_PUBLIC_READ_WRITE = 'public-read-write'; 
private static $__accessKey; // AWS Access key 
private static $__secretKey; // AWS Secret key 
public static $_uploadProgressFileName="" ;//uploadProgressFileName 
public function __construct($accessKey = null, $secretKey = null) { 
if ($accessKey !== null && $secretKey !== null) 
self::setAuth($accessKey, $secretKey); 
} 
public static function setAuth($accessKey, $secretKey) { 
self::$__accessKey = $accessKey; 
self::$__secretKey = $secretKey; 
} 
public static function listBuckets($detailed = false) { 
$rest = new S3Request('GET', '', ''); 
$rest = $rest->getResponse(); 
if ($rest->error === false && $rest->code !== 200) 
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status'); 
if ($rest->error !== false) { 
trigger_error(sprintf("S3Withprogressbar::listBuckets(): [%s] %s", $rest->error['code'], $rest->error['message']), E_USER_WARNING); 
return false; 
} 
$results = array(); //var_dump($rest->body); 
if (!isset($rest->body->Buckets)) return $results; 
if ($detailed) { 
if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName)) 
$results['owner'] = array(
'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->ID 
); 
$results['buckets'] = array(); 
foreach ($rest->body->Buckets->Bucket as $b) 
$results['buckets'][] = array(
'name' => (string)$b->Name, 'time' => strtotime((string)$b->CreationDate) 
); 
} else 
foreach ($rest->body->Buckets->Bucket as $b) $results[] = (string)$b->Name; 
return $results; 
} 
public static function getBucket($bucket, $prefix = null, $marker = null, $maxKeys = null) { 
$rest = new S3Request('GET', $bucket, ''); 
if ($prefix !== null && $prefix !== '') $rest->setParameter('prefix', $prefix); 
if ($marker !== null && $prefix !== '') $rest->setParameter('marker', $marker); 
if ($maxKeys !== null && $prefix !== '') $rest->setParameter('max-keys', $maxKeys); 
$response = $rest->getResponse(); 
if ($response->error === false && $response->code !== 200) 
$response->error = array('code' => $response->code, 'message' => 'Unexpected HTTP status'); 
if ($response->error !== false) { 
trigger_error(sprintf("S3Withprogressbar::getBucket(): [%s] %s", $response->error['code'], $response->error['message']), E_USER_WARNING); 
return false; 
} 
$results = array(); 
$lastMarker = null; 
if (isset($response->body, $response->body->Contents)) 
foreach ($response->body->Contents as $c) { 
$results[(string)$c->Key] = array(
'name' => (string)$c->Key, 
'time' => strToTime((string)$c->LastModified), 
'size' => (int)$c->Size, 
'hash' => substr((string)$c->ETag, 1, -1) 
); 
$lastMarker = (string)$c->Key; 
//$response->body->IsTruncated = 'true'; break; 
} 
if (isset($response->body->IsTruncated) && 
(string)$response->body->IsTruncated == 'false') return $results; 
// Loop through truncated results if maxKeys isn't specified 
if ($maxKeys == null && $lastMarker !== null && (string)$response->body->IsTruncated == 'true') 
do { 
$rest = new S3Request('GET', $bucket, ''); 
if ($prefix !== null) $rest->setParameter('prefix', $prefix); 
$rest->setParameter('marker', $lastMarker); 
if (($response = $rest->getResponse(true)) == false || $response->code !== 200) break; 
if (isset($response->body, $response->body->Contents)) 
foreach ($response->body->Contents as $c) { 
$results[(string)$c->Key] = array(
'name' => (string)$c->Key, 
'time' => strToTime((string)$c->LastModified), 
'size' => (int)$c->Size, 
'hash' => substr((string)$c->ETag, 1, -1) 
); 
$lastMarker = (string)$c->Key; 
} 
} while ($response !== false && (string)$response->body->IsTruncated == 'true'); 
return $results; 
} 
public function putBucket($bucket, $acl = self::ACL_PRIVATE) { 
$rest = new S3Request('PUT', $bucket, ''); 
$rest->setAmzHeader('x-amz-acl', $acl); 
$rest = $rest->getResponse(); 
if ($rest->error === false && $rest->code !== 200) 
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status'); 
if ($rest->error !== false) { 
//trigger_error(sprintf("S3Withprogressbar::putBucket({$bucket}): [%s] %s", $rest->error['code'], $rest->error['message']), E_USER_WARNING); 
return false; 
} 
return true; 
} 
public function deleteBucket($bucket = '') { 
$rest = new S3Request('DELETE', $bucket); 
$rest = $rest->getResponse(); 
if ($rest->error === false && $rest->code !== 204) 
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status'); 
if ($rest->error !== false) { 
trigger_error(sprintf("S3Withprogressbar::deleteBucket({$bucket}): [%s] %s", 
$rest->error['code'], $rest->error['message']), E_USER_WARNING); 
return false; 
} 
return true; 
} 
public static function inputFile($file, $md5sum = true) { 
if (!file_exists($file) || !is_file($file) || !is_readable($file)) { 
trigger_error('S3Withprogressbar::inputFile(): Unable to open input file: '.$file, E_USER_WARNING); 
return false; 
} 
return array('file' => $file, 'size' => filesize($file), 
'md5sum' => $md5sum !== false ? (is_string($md5sum) ? $md5sum : 
base64_encode(md5_file($file, true))) : ''); 
} 
public static function inputResource(&$resource, $bufferSize, $md5sum = '') { 
if (!is_resource($resource) || $bufferSize <= 0) { 
trigger_error('S3Withprogressbar::inputResource(): Invalid resource or buffer size', E_USER_WARNING); 
return false; 
} 
$input = array('size' => $bufferSize, 'md5sum' => $md5sum); 
$input['fp'] =& $resource; 
return $input; 
} 
// Modified Function with one more parameter $uploadProgressFileName 
public static function putObject($input, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = null,$uploadProgressFileName) { 
if ($input == false) return false; 
$rest = new S3Request('PUT', $bucket, $uri); 
// Set public variable value($uploadProgressFileName) in S3Request class 
$rest->uploadProgressFileName = $uploadProgressFileName; 
if (is_string($input)) $input = array(
'data' => $input, 'size' => strlen($input), 
'md5sum' => base64_encode(md5($input, true)) 
); 
// Data 
if (isset($input['fp'])) 
$rest->fp =& $input['fp']; 
elseif (isset($input['file'])) 
$rest->fp = @fopen($input['file'], 'rb'); 
elseif (isset($input['data'])) 
$rest->data = $input['data']; 
// Content-Length (required) 
if (isset($input['size']) && $input['size'] > 0) 
$rest->size = $input['size']; 
else { 
if (isset($input['file'])) 
$rest->size = filesize($input['file']); 
elseif (isset($input['data'])) 
$rest->size = strlen($input['data']); 
} 
// Content-Type 
if ($contentType !== null) 
$input['type'] = $contentType; 
elseif (!isset($input['type']) && isset($input['file'])) 
$input['type'] = self::__getMimeType($input['file']); 
else 
$input['type'] = 'application/octet-stream'; 
// We need to post with the content-length and content-type, MD5 is optional 
if ($rest->size > 0 && ($rest->fp !== false || $rest->data !== false)) { 
$rest->setHeader('Content-Type', $input['type']); 
if (isset($input['md5sum'])) $rest->setHeader('Content-MD5', $input['md5sum']); 
$rest->setAmzHeader('x-amz-acl', $acl); 
foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v); 
$rest->getResponse(); 
} else 
$rest->response->error = array('code' => 0, 'message' => 'Missing input parameters'); 
if ($rest->response->error === false && $rest->response->code !== 200) 
$rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status'); 
if ($rest->response->error !== false) { 
//trigger_error(sprintf("S3Withprogressbar::putObject(): [%s] %s", $rest->response->error['code'], $rest->response->error['message']), E_USER_WARNING); 
return false; 
} 
return true; 
} 
// Modified Function with one more parameter $uploadProgressFileName 
public static function putObjectFile($file, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = null,$uploadProgressFileName) { 
return self::putObject(S3Withprogressbar::inputFile($file), $bucket, $uri, $acl, $metaHeaders, $contentType,$uploadProgressFileName); 
} 
public function putObjectString($string, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = 'text/plain') { 
return self::putObject($string, $bucket, $uri, $acl, $metaHeaders, $contentType); 
} 
public static function getObject($bucket = '', $uri = '', $saveTo = false) { 
$rest = new S3Request('GET', $bucket, $uri); 
if ($saveTo !== false) { 
if (is_resource($saveTo)) 
$rest->fp =& $saveTo; 
else 
if (($rest->fp = @fopen($saveTo, 'wb')) == false) 
$rest->response->error = array('code' => 0, 'message' => 'Unable to open save file for writing: '.$saveTo); 
} 
if ($rest->response->error === false) $rest->getResponse(); 
if ($rest->response->error === false && $rest->response->code !== 200) 
$rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status'); 
if ($rest->response->error !== false) { 
trigger_error(sprintf("S3Withprogressbar::getObject({$bucket}, {$uri}): [%s] %s", 
$rest->response->error['code'], $rest->response->error['message']), E_USER_WARNING); 
return false; 
} 
$rest->file = realpath($saveTo); 
return $rest->response; 
} 
public static function getObjectInfo($bucket = '', $uri = '', $returnInfo = true) { 
$rest = new S3Request('HEAD', $bucket, $uri); 
$rest = $rest->getResponse(); 
if ($rest->error === false && ($rest->code !== 200 && $rest->code !== 404)) 
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status'); 
if ($rest->error !== false) { 
trigger_error(sprintf("S3Withprogressbar::getObjectInfo({$bucket}, {$uri}): [%s] %s", 
$rest->error['code'], $rest->error['message']), E_USER_WARNING); 
return false; 
} 
return $rest->code == 200 ? $returnInfo ? $rest->headers : true : false; 
} 
public static function setBucketLogging($bucket, $targetBucket, $targetPrefix) { 
$dom = new DOMDocument; 
$bucketLoggingStatus = $dom->createElement('BucketLoggingStatus'); 
$bucketLoggingStatus->setAttribute('xmlns', 'http://s3.amazonaws.com/doc/2006-03-01/'); 
$loggingEnabled = $dom->createElement('LoggingEnabled'); 
$loggingEnabled->appendChild($dom->createElement('TargetBucket', $targetBucket)); 
$loggingEnabled->appendChild($dom->createElement('TargetPrefix', $targetPrefix)); 
// TODO: Add TargetGrants 
$bucketLoggingStatus->appendChild($loggingEnabled); 
$dom->appendChild($bucketLoggingStatus); 
$rest = new S3Request('PUT', $bucket, ''); 
$rest->setParameter('logging', null); 
$rest->data = $dom->saveXML(); 
$rest->size = strlen($rest->data); 
$rest->setHeader('Content-Type', 'application/xml'); 
$rest = $rest->getResponse(); 
if ($rest->error === false && $rest->code !== 200) 
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status'); 
if ($rest->error !== false) { 
trigger_error(sprintf("S3Withprogressbar::setBucketLogging({$bucket}, {$uri}): [%s] %s", 
$rest->error['code'], $rest->error['message']), E_USER_WARNING); 
return false; 
} 
return true; 
} 
public static function getBucketLogging($bucket = '') { 
$rest = new S3Request('GET', $bucket, ''); 
$rest->setParameter('logging', null); 
$rest = $rest->getResponse(); 
if ($rest->error === false && $rest->code !== 200) 
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status'); 
if ($rest->error !== false) { 
trigger_error(sprintf("S3Withprogressbar::getBucketLogging({$bucket}): [%s] %s", 
$rest->error['code'], $rest->error['message']), E_USER_WARNING); 
return false; 
} 
if (!isset($rest->body->LoggingEnabled)) return false; // No logging 
return array(
'targetBucket' => (string)$rest->body->LoggingEnabled->TargetBucket, 
'targetPrefix' => (string)$rest->body->LoggingEnabled->TargetPrefix, 
); 
} 
public static function setAccessControlPolicy($bucket, $uri = '', $acp = array()) { 
$dom = new DOMDocument; 
$dom->formatOutput = true; 
$accessControlPolicy = $dom->createElement('AccessControlPolicy'); 
$accessControlList = $dom->createElement('AccessControlList'); 
// It seems the owner has to be passed along too 
$owner = $dom->createElement('Owner'); 
$owner->appendChild($dom->createElement('ID', $acp['owner']['id'])); 
$owner->appendChild($dom->createElement('DisplayName', $acp['owner']['name'])); 
$accessControlPolicy->appendChild($owner); 
foreach ($acp['acl'] as $g) { 
$grant = $dom->createElement('Grant'); 
$grantee = $dom->createElement('Grantee'); 
$grantee->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); 
if (isset($g['id'])) { // CanonicalUser (DisplayName is omitted) 
$grantee->setAttribute('xsi:type', 'CanonicalUser'); 
$grantee->appendChild($dom->createElement('ID', $g['id'])); 
} elseif (isset($g['email'])) { // AmazonCustomerByEmail 
$grantee->setAttribute('xsi:type', 'AmazonCustomerByEmail'); 
$grantee->appendChild($dom->createElement('EmailAddress', $g['email'])); 
} elseif ($g['type'] == 'Group') { // Group 
$grantee->setAttribute('xsi:type', 'Group'); 
$grantee->appendChild($dom->createElement('URI', $g['uri'])); 
} 
$grant->appendChild($grantee); 
$grant->appendChild($dom->createElement('Permission', $g['permission'])); 
$accessControlList->appendChild($grant); 
} 
$accessControlPolicy->appendChild($accessControlList); 
$dom->appendChild($accessControlPolicy); 
$rest = new S3Request('PUT', $bucket, ''); 
$rest->setParameter('acl', null); 
$rest->data = $dom->saveXML(); 
$rest->size = strlen($rest->data); 
$rest->setHeader('Content-Type', 'application/xml'); 
$rest = $rest->getResponse(); 
if ($rest->error === false && $rest->code !== 200) 
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status'); 
if ($rest->error !== false) { 
trigger_error(sprintf("S3Withprogressbar::setAccessControlPolicy({$bucket}, {$uri}): [%s] %s", 
$rest->error['code'], $rest->error['message']), E_USER_WARNING); 
return false; 
} 
return true; 
} 
public static function getAccessControlPolicy($bucket, $uri = '') { 
$rest = new S3Request('GET', $bucket, $uri); 
$rest->setParameter('acl', null); 
$rest = $rest->getResponse(); 
if ($rest->error === false && $rest->code !== 200) 
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status'); 
if ($rest->error !== false) { 
trigger_error(sprintf("S3Withprogressbar::getAccessControlPolicy({$bucket}, {$uri}): [%s] %s", 
$rest->error['code'], $rest->error['message']), E_USER_WARNING); 
return false; 
} 
$acp = array(); 
if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName)) { 
$acp['owner'] = array(
'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->DisplayName 
); 
} 
if (isset($rest->body->AccessControlList)) { 
$acp['acl'] = array(); 
foreach ($rest->body->AccessControlList->Grant as $grant) { 
foreach ($grant->Grantee as $grantee) { 
if (isset($grantee->ID, $grantee->DisplayName)) // CanonicalUser 
$acp['acl'][] = array(
'type' => 'CanonicalUser', 
'id' => (string)$grantee->ID, 
'name' => (string)$grantee->DisplayName, 
'permission' => (string)$grant->Permission 
); 
elseif (isset($grantee->EmailAddress)) // AmazonCustomerByEmail 
$acp['acl'][] = array(
'type' => 'AmazonCustomerByEmail', 
'email' => (string)$grantee->EmailAddress, 
'permission' => (string)$grant->Permission 
); 
elseif (isset($grantee->URI)) // Group 
$acp['acl'][] = array(
'type' => 'Group', 
'uri' => (string)$grantee->URI, 
'permission' => (string)$grant->Permission 
); 
else continue; 
} 
} 
} 
return $acp; 
} 
public static function deleteObject($bucket = '', $uri = '') { 
$rest = new S3Request('DELETE', $bucket, $uri); 
$rest = $rest->getResponse(); 
if ($rest->error === false && $rest->code !== 204) 
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status'); 
if ($rest->error !== false) { 
trigger_error(sprintf("S3Withprogressbar::deleteObject(): [%s] %s", $rest->error['code'], $rest->error['message']), E_USER_WARNING); 
return false; 
} 
return true; 
} 
public static function __getMimeType(&$file) { 
$type = false; 
// Fileinfo documentation says fileinfo_open() will use the 
// MAGIC env var for the magic file 
if (extension_loaded('fileinfo') && isset($_ENV['MAGIC']) && 
($finfo = finfo_open(FILEINFO_MIME, $_ENV['MAGIC'])) !== false) { 
if (($type = finfo_file($finfo, $file)) !== false) { 
// Remove the charset and grab the last content-type 
$type = explode(' ', str_replace('; charset=', ';charset=', $type)); 
$type = array_pop($type); 
$type = explode(';', $type); 
$type = array_shift($type); 
} 
finfo_close($finfo); 
// If anyone is still using mime_content_type() 
} elseif (function_exists('mime_content_type')) 
$type = mime_content_type($file); 
if ($type !== false && strlen($type) > 0) return $type; 
// Otherwise do it the old fashioned way 
static $exts = array(
'jpg' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png', 
'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'ico' => 'image/x-icon', 
'swf' => 'application/x-shockwave-flash', 'pdf' => 'application/pdf', 
'zip' => 'application/zip', 'gz' => 'application/x-gzip', 
'tar' => 'application/x-tar', 'bz' => 'application/x-bzip', 
'bz2' => 'application/x-bzip2', 'txt' => 'text/plain', 
'asc' => 'text/plain', 'htm' => 'text/html', 'html' => 'text/html', 
'xml' => 'text/xml', 'xsl' => 'application/xsl+xml', 
'ogg' => 'application/ogg', 'mp3' => 'audio/mpeg', 'wav' => 'audio/x-wav', 
'avi' => 'video/x-msvideo', 'mpg' => 'video/mpeg', 'mpeg' => 'video/mpeg', 
'mov' => 'video/quicktime', 'flv' => 'video/x-flv', 'php' => 'text/x-php' 
); 
$ext = strToLower(pathInfo($file, PATHINFO_EXTENSION)); 
return isset($exts[$ext]) ? $exts[$ext] : 'application/octet-stream'; 
} 
public static function __getSignature($string) { 
return 'AWS '.self::$__accessKey.':'.base64_encode(extension_loaded('hash') ? 
hash_hmac('sha1', $string, self::$__secretKey, true) : pack('H*', sha1(
(str_pad(self::$__secretKey, 64, chr(0x00))^(str_repeat(chr(0x5c), 64))) . 
pack('H*', sha1((str_pad(self::$__secretKey, 64, chr(0x00))^
(str_repeat(chr(0x36), 64))) . $string))))); 
} 
} 
final class S3Request { 
private $verb, $bucket, $uri, $resource = '', $parameters = array(), 
$amzHeaders = array(), $headers = array(
'Host' => '', 'Date' => '', 'Content-MD5' => '', 'Content-Type' => '' 
); 
public $fp = false, $size = 0, $data = false, $response; 
public $uploadProgressFileName; 
function __construct($verb, $bucket = '', $uri = '') { 
$this->verb = $verb; 
$this->bucket = strtolower($bucket); 
$this->uri = $uri !== '' ? '/'.$uri : '/'; 
if ($this->bucket !== '') { 
$this->bucket = explode('/', $this->bucket); 
$this->resource = '/'.$this->bucket[0].$this->uri; 
$this->headers['Host'] = $this->bucket[0].'.s3.amazonaws.com'; 
$this->bucket = implode('/', $this->bucket); 
} else { 
$this->headers['Host'] = 's3.amazonaws.com'; 
if (strlen($this->uri) > 1) 
$this->resource = '/'.$this->bucket.$this->uri; 
else $this->resource = $this->uri; 
} 
$this->headers['Date'] = gmdate('D, d M Y H:i:s T'); 
$this->response = new STDClass; 
$this->response->error = false; 
$this->response->body = false; 
$CI =& get_instance(); 
$CI->load->helper('file'); 
} 
public function setParameter($key, $value) { 
$this->parameters[$key] = $value; 
} 
public function setHeader($key, $value) { 
$this->headers[$key] = $value; 
} 
public function setAmzHeader($key, $value) { 
$this->amzHeaders[$key] = $value; 
} 
//:callback function for upload progress. 
public function progressCallback_new_curl($new,$download_size, $downloaded_size, $upload_size, $uploaded_size) 
{ 
ob_start(); 
static $previousProgress = 0; 
if ($upload_size == 0) 
$progress = 0; 
else 
$progress = round($uploaded_size * 100/$upload_size); 
if ($progress > $previousProgress) 
{ 
flush(); 
$previousProgress = $progress; 
$new_file_path = FCPATH.'upload/'.$this->uploadProgressFileName.'.txt'; // modify this line to point to the actual location of the file 
write_file($new_file_path, $progress."\n"); 
// Check for Cancel upload text file and if exists return 1 to interrupt curl upload process. 
$cancel_path=FCPATH.'upload/cancel_'.$this->uploadProgressFileName.'.txt'; 
if(file_exists($cancel_path)){ 
unlink($cancel_path); 
if(file_exists($new_file_path)){ 
unlink($new_file_path); 
} 
return 1; 
} 
}   
ob_flush(); 
flush();       
} 
public function progressCallback_old_curl($download_size, $downloaded_size, $upload_size, $uploaded_size) 
{ 
ob_start(); 
static $previousProgress = 0; 
if ($upload_size == 0) 
$progress = 0; 
else 
$progress = round($uploaded_size * 100/$upload_size); 
if ($progress > $previousProgress) 
{ 
flush(); 
$previousProgress = $progress; 
$new_file_path = FCPATH.'upload/'.$this->uploadProgressFileName.'.txt'; // modify this line to point to the actual location of the file 
write_file($new_file_path, $progress."\n"); 
// Check for Cancel upload text file and if exists return 1 to interrupt curl upload process. 
$cancel_path=FCPATH.'upload/cancel_'.$this->uploadProgressFileName.'.txt'; 
if(file_exists($cancel_path)){ 
unlink($cancel_path); 
if(file_exists($new_file_path)){ 
unlink($new_file_path); 
} 
return 1; 
} 
} 
ob_flush(); 
flush(); 
} 
public function getResponse() { 
$query = ''; 
if (sizeof($this->parameters) > 0) { 
$query = substr($this->uri, -1) !== '?' ? '?' : '&'; 
foreach ($this->parameters as $var => $value) 
if ($value == null || $value == '') $query .= $var.'&'; 
else $query .= $var.'='.$value.'&'; 
$query = substr($query, 0, -1); 
$this->uri .= $query; 
if (isset($this->parameters['acl']) || !isset($this->parameters['logging'])) 
$this->resource .= $query; 
} 
$url = (extension_loaded('openssl')?'https://':'http://').$this->headers['Host'].$this->uri; 
//var_dump($this->bucket, $this->uri, $this->resource, $url); 
// Basic setup 
$curl = curl_init(); 
curl_setopt($curl, CURLOPT_USERAGENT, 'S3/php'); 
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); 
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); 
curl_setopt($curl, CURLOPT_URL, $url); 
//:callback function call for upload progress. 
curl_setopt($curl, CURLOPT_NOPROGRESS, false); 
if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 50500) { 
curl_setopt($curl, CURLOPT_PROGRESSFUNCTION, array($this, 'progressCallback_old_curl')); 
} else { 
curl_setopt($curl, CURLOPT_PROGRESSFUNCTION, array($this, 'progressCallback_new_curl')); 
} 
// Headers 
$headers = array(); $amz = array(); 
foreach ($this->amzHeaders as $header => $value) 
if (strlen($value) > 0) $headers[] = $header.': '.$value; 
foreach ($this->headers as $header => $value) 
if (strlen($value) > 0) $headers[] = $header.': '.$value; 
foreach ($this->amzHeaders as $header => $value) 
if (strlen($value) > 0) $amz[] = strToLower($header).':'.$value; 
$amz = (sizeof($amz) > 0) ? "\n".implode("\n", $amz) : ''; 
// Authorization string 
$headers[] = 'Authorization: ' . S3Withprogressbar::__getSignature(
$this->verb."\n". 
$this->headers['Content-MD5']."\n". 
$this->headers['Content-Type']."\n". 
$this->headers['Date'].$amz."\n".$this->resource 
); 
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); 
curl_setopt($curl, CURLOPT_HEADER, false); 
curl_setopt($curl, CURLOPT_RETURNTRANSFER, false); 
curl_setopt($curl, CURLOPT_WRITEFUNCTION, array(&$this, '__responseWriteCallback')); 
curl_setopt($curl, CURLOPT_HEADERFUNCTION, array(&$this, '__responseHeaderCallback')); 
// Request types 
switch ($this->verb) { 
case 'GET': break; 
case 'PUT': 
if ($this->fp !== false) { 
curl_setopt($curl, CURLOPT_PUT, true); 
curl_setopt($curl, CURLOPT_INFILE, $this->fp); 
if ($this->size > 0) 
curl_setopt($curl, CURLOPT_INFILESIZE, $this->size); 
} elseif ($this->data !== false) { 
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT'); 
curl_setopt($curl, CURLOPT_POSTFIELDS, $this->data); 
if ($this->size > 0) 
curl_setopt($curl, CURLOPT_BUFFERSIZE, $this->size); 
} else 
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT'); 
break; 
case 'HEAD': 
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'HEAD'); 
curl_setopt($curl, CURLOPT_NOBODY, true); 
break; 
case 'DELETE': 
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE'); 
break; 
default: break; 
} 
// Execute, grab errors 
if (curl_exec($curl)) 
$this->response->code = curl_getinfo($curl, CURLINFO_HTTP_CODE); 
else 
$this->response->error = array(
'code' => curl_errno($curl), 
'message' => curl_error($curl), 
'resource' => $this->resource 
); 
@curl_close($curl); 
// Parse body into XML 
if ($this->response->error === false && isset($this->response->headers['type']) && 
$this->response->headers['type'] == 'application/xml' && isset($this->response->body)) { 
$this->response->body = simplexml_load_string($this->response->body); 
// Grab S3 errors 
if (!in_array($this->response->code, array(200, 204)) && 
isset($this->response->body->Code, $this->response->body->Message)) { 
$this->response->error = array(
'code' => (string)$this->response->body->Code, 
'message' => (string)$this->response->body->Message 
); 
if (isset($this->response->body->Resource)) 
$this->response->error['resource'] = (string)$this->response->body->Resource; 
unset($this->response->body); 
} 
} 
// Clean up file resources 
if ($this->fp !== false && is_resource($this->fp)) fclose($this->fp); 
return $this->response; 
} 
private function __responseWriteCallback(&$curl, &$data) { 
if ($this->response->code == 200 && $this->fp !== false) 
return fwrite($this->fp, $data); 
else 
$this->response->body .= $data; 
return strlen($data); 
} 
private function __responseHeaderCallback(&$curl, &$data) { 
if (($strlen = strlen($data)) <= 2) return $strlen; 
if (substr($data, 0, 4) == 'HTTP') 
$this->response->code = (int)substr($data, 9, 3); 
else { 
list($header, $value) = explode(': ', trim($data)); 
if ($header == 'Last-Modified') 
$this->response->headers['time'] = strtotime($value); 
elseif ($header == 'Content-Length') 
$this->response->headers['size'] = (int)$value; 
elseif ($header == 'Content-Type') 
$this->response->headers['type'] = $value; 
elseif ($header == 'ETag') 
$this->response->headers['hash'] = substr($value, 1, -1); 
elseif (preg_match('/^x-amz-meta-.*$/', $header)) 
$this->response->headers[$header] = is_numeric($value) ? (int)$value : $value; 
} 
return $strlen; 
} 
} 
?>