0

I'm trying to rename each file before uploading to Amazon S3.

I am trying to use this exact method of which was answered by @Silvertiger: PHP - upload and overwrite a file (or upload and rename it)?

If exists, rename to a random name although somehow it doesn't work.

Here is the upload post Parameter from the Amazon S3 Class:

public static function getHttpUploadPostParams($bucket, $uriPrefix = '', $acl = self::ACL_PRIVATE, $lifetime = 3600,
    $maxFileSize = 5242880, $successRedirect = "201", $amzHeaders = array(), $headers = array(), $flashVars = false)
    {
        // Create policy object
        $policy = new stdClass;
        $policy->expiration = gmdate('Y-m-d\TH:i:s\Z', (time() + $lifetime));
        $policy->conditions = array();
        $obj = new stdClass; $obj->bucket = $bucket; array_push($policy->conditions, $obj);
        $obj = new stdClass; $obj->acl = $acl; array_push($policy->conditions, $obj);

        $obj = new stdClass; // 200 for non-redirect uploads
        if (is_numeric($successRedirect) && in_array((int)$successRedirect, array(200, 201)))
            $obj->success_action_status = (string)$successRedirect;
        else // URL
            $obj->success_action_redirect = $successRedirect;
        array_push($policy->conditions, $obj);

        if ($acl !== self::ACL_PUBLIC_READ)
            array_push($policy->conditions, array('eq', '$acl', $acl));

        array_push($policy->conditions, array('starts-with', '$key', $uriPrefix));
        if ($flashVars) array_push($policy->conditions, array('starts-with', '$Filename', ''));
        foreach (array_keys($headers) as $headerKey)
            array_push($policy->conditions, array('starts-with', '$'.$headerKey, ''));
        foreach ($amzHeaders as $headerKey => $headerVal)
        {
            $obj = new stdClass;
            $obj->{$headerKey} = (string)$headerVal;
            array_push($policy->conditions, $obj);
        }
        array_push($policy->conditions, array('content-length-range', 0, $maxFileSize));
        $policy = base64_encode(str_replace('\/', '/', json_encode($policy)));

        // Create parameters
        $params = new stdClass;
        $params->AWSAccessKeyId = self::$__accessKey;
        $params->key = $uriPrefix.'${filename}';
        $params->acl = $acl;
        $params->policy = $policy; unset($policy);
        $params->signature = self::__getHash($params->policy);
        if (is_numeric($successRedirect) && in_array((int)$successRedirect, array(200, 201)))
            $params->success_action_status = (string)$successRedirect;
        else
            $params->success_action_redirect = $successRedirect;
        foreach ($headers as $headerKey => $headerVal) $params->{$headerKey} = (string)$headerVal;
        foreach ($amzHeaders as $headerKey => $headerVal) $params->{$headerKey} = (string)$headerVal;
        return $params;
    }

Here is @Silvertiger's method:

// this assumes that the upload form calls the form file field "myupload"
$name  = $_FILES['myupload']['name'];
$type  = $_FILES['myupload']['type'];
$size  = $_FILES['myupload']['size'];
$tmp   = $_FILES['myupload']['tmp_name'];
$error = $_FILES['myupload']['error'];
$savepath = '/yourserverpath/';
$filelocation = $svaepath.$name;
// This won't upload if there was an error or if the file exists, hence the check
if (!file_exists($filelocation) && $error == 0) {
    // echo "The file $filename exists";
    // This will overwrite even if the file exists
    move_uploaded_file($tmp, $filelocation);
}
// OR just leave out the "file_exists()" and check for the error,
// an if statement either way

This is my upload form:

    <form method="post" action="<?php echo $uploadURL; ?>" enctype="multipart/form-data">
<?php
    foreach ($params as $p => $v)
        echo "        <input type=\"hidden\" name=\"{$p}\" value=\"{$v}\" />\n";
?>
        <input type="file" name="file" />&#160;<input type="submit" value="Upload" />
    </form>

And this is the Input info:

public static function inputFile($file, $md5sum = true)
    {
        if (!file_exists($file) || !is_file($file) || !is_readable($file))
        {
            self::__triggerError('S3::inputFile(): Unable to open input file: '.$file, __FILE__, __LINE__);
            return false;
        }
        return array('file' => $file, 'size' => filesize($file), 'md5sum' => $md5sum !== false ?
        (is_string($md5sum) ? $md5sum : base64_encode(md5_file($file, true))) : '');
    }
Community
  • 1
  • 1
jQuerybeast
  • 14,130
  • 38
  • 118
  • 196
  • Where in this mess of code are you attempting to rename the file? You posted 'input info', but there are no calls to `::inputFile`. – Mike Purcell Apr 24 '12 at 00:01
  • I've posted the function where the input info array is created. I would assume I would rename the file before passing it to that array. If I knew exactly where I should rename, I wouldn't be asking. Im asking because I cant find it. Here is the class: https://github.com/tpyo/amazon-s3-php-class/blob/master/S3.php – jQuerybeast Apr 24 '12 at 00:05

3 Answers3

2

You can do your renaming at this point in your code:

move_uploaded_file($tmp, $filelocation);

The $filelocation can be changed to whatever you want and the uploaded file will be renamed to that path.

Edit: The S3::getHttpUploadPostParams method always uses the file name from the upload to create the S3 resource. To change that you have to copy the method but change this line:

$params->key = $uriPrefix.'${filename}';

The '${filename} must be changed to a path of your choosing.

Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
  • Hi sir. The move_upload_file come from this answer: http://stackoverflow.com/questions/8919804/php-upload-and-overwrite-a-file-or-upload-and-rename-it which I don't know where to include the snippet. It does not exists in my files. This is my class: https://github.com/tpyo/amazon-s3-php-class/blob/master/S3.php – jQuerybeast Apr 24 '12 at 16:03
  • That's Amazon's S3 class, I'm pretty sure you didn't write that :) The S3 code to upload the file comes after the `move_uploaded_file()` call (make sure the result is `true`) – Ja͢ck Apr 25 '12 at 03:48
  • I didnt said im the author, but it is the class I am using. None of my files contains move_upload_files(). Here is my index file: http://pastebin.com/VDjsdGng In my question, move_uploaded_file() comes from @Silvertiger's answer on another question. That it is not my code – jQuerybeast Apr 25 '12 at 05:12
  • That makes more sense. Updated my answer. – Ja͢ck Apr 25 '12 at 05:50
  • Ok here is the problem. I changed $filename to something random. Look at here: http://pastebin.com/4M4aCw8S but the actual name is the variable I set – jQuerybeast Apr 25 '12 at 16:09
2

Replace this:

// Create parameters
$params = new stdClass;
$params->AWSAccessKeyId = self::$__accessKey;
$params->key = $uriPrefix.'${filename}';

with this:

function rand_string( $length ) {
            $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";  

            $size = strlen( $chars );
            for( $i = 0; $i < $length; $i++ ) {
                $str .= $chars[ rand( 0, $size - 1 ) ];
            }

            return $str;
        }       

        // Create parameters
        $params = new stdClass;
        $params->AWSAccessKeyId = self::$__accessKey;
        $params->key = $uriPrefix.rand_string(5).'${filename}';
jQuerybeast
  • 14,130
  • 38
  • 118
  • 196
  • It is not a third party vendor code. It's a class that an appreciated developer created. Classes like these are developed for a wide range of other developers and not specifically for you, me or jQuerybeast. If you need something specific that the author didn't thought, had time or didn't care about, your override it to fit your needs. If you are a developer you should know that nothing is ready for you. There are shortcuts (like these classes), but nothing will fit your needs. If everything was ready, we wouldn't need developers. – jQuerybeast Apr 26 '12 at 04:11
  • So what happens the the appreciated developer updates his code and releases it, you going to remember to copy and paste the new contents and re-apply the patch? – Mike Purcell Apr 26 '12 at 04:12
  • If the appreciated developer updates his class, you check what he included in the new one and if you do need the changes then you added them yourself. Otherwise, you would probably just keep updating the class, no matter if you are only using 1 feature of it. It's like you would want to use jQuery UI draggable and instead you include the entire project (made by other appreciated developers) of 362KB instead of the 29KB of which is the draggable. – jQuerybeast Apr 26 '12 at 04:17
  • 1
    The more widely accepted practice is to extend the 3rd party API so you can add custom changes without affecting source code. This is exactly what I have been trying to get OP to understand. If he posted the form handling to an intermediary actions script he could instantiate custom version of the API and add the image. – Mike Purcell Apr 26 '12 at 04:20
  • Not trying to dissuade your answer, just curious on the approach is all. As you stated it obviously worked for him. – Mike Purcell Apr 26 '12 at 19:43
0

You can easily put this code.. 100 percent working.

<?php
$file=$_FILES['file']['name'];
$path ="upload/".$file;
$ext=pathinfo($path,PATHINFO_EXTENSION);
$name=pathinfo($path,PATHINFO_FILENAME);
if(file_exists($path))
{
    echo "File alredy exists .So name is changed automatically & moved";
    $path1="upload/";
    $new_name=$path1.$name.rand(1,500).".".$ext;
    move_uploaded_file($_FILES['file']['tmp_name'],$new_name);
}
else
{
echo"uploaded Sucessfully without any change";
move_uploaded_file($_FILES['file']['tmp_name'],$path);
}
?>