Problem with sprintf error when using S3->copyObject() and filenames with % in them
I am using PHP S3.PHP class to manage files on Amazon S3. I use the copyObject() function to copy files in my S3 bucket. All works great until I meet filenames that need to be urlencoded (I urlencode everything anyway). When a filename ends up with % characters in it the copyObject() function spits the dummy.
for example - the filename 63037_Copy%287%29ofDSC_1337.JPG throws the following error when passed to copyObject() -
Warning: sprintf() [<a href='function.sprintf'>function.sprintf</a>]: Too few arguments in ..... S3.php on line 477
Here's the copyObject function line 477
public static function copyObject($srcBucket, $srcUri, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array()) {
$rest = new S3Request('PUT', $bucket, $uri);
$rest->setHeader('Content-Length', 0);
foreach ($requestHeaders as $h => $v) $rest->setHeader($h, $v);
foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
$rest->setAmzHeader('x-amz-acl', $acl);
$rest->setAmzHeader('x-amz-copy-source', sprintf('/%s/%s', $srcBucket, $srcUri));
if (sizeof($requestHeaders) > 0 || sizeof($metaHeaders) > 0)
$rest->setAmzHeader('x-amz-metadata-directive', 'REPLACE');
$rest = $rest->getResponse();
if ($rest->error === false && $rest->code !== 200)
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
if ($rest->error !== false) {
-------------------------------------------- LINE 477 ----------------------------
**trigger_error(sprintf("S3::copyObject({$srcBucket}, {$srcUri}, {$bucket}, {$uri}): [%s] %s",
$rest->error['code'], $rest->error['message']), E_USER_WARNING);**
-------------------------------------------- LINE 477 ----------------------------
return false;
}
return isset($rest->body->LastModified, $rest->body->ETag) ? array(
'time' => strtotime((string)$rest->body->LastModified),
'hash' => substr((string)$rest->body->ETag, 1, -1)
) : false;
}
Has anyone come across this before? There is absolutely no problem when using filenames which don't change when urlencoded, and Ive already tried removing all whitespace from filenames but wont be able to catch all characters, like brackets which is the problem in the example here. And I dont want to go down that road anyway as I want to keep the filename开发者_JAVA百科s as close to the original as possible.
thanks guys
Redo the line this way:
trigger_error("S3::copyObject({$srcBucket}, {$srcUri}, {$bucket}, {$uri}): ". sprintf("[%s] %s",
$rest->error['code'], $rest->error['message']), E_USER_WARNING);
%'s in the first parameter to sprintf are identified as the placeholders for values. Because your filenames are first inserted in the string and that string is then passed to sprintf(), sprintf() mistakenly interprets the %'s in the file names as placeholders.
精彩评论