Hello!
I'm pretty new to this and I realize this question may not be specific to the SDK. I'm trying to create an upload form to add a file into a folder within a bucket using AwsS3PostObjectV4.
I'm guessing I have to set the key with the name of the folder like so:
// Set some defaults for form input fields
$formInputs = [
'acl' => 'public-read',
'key' => 'folder/{$filename}'
];
And later pass those form inputs to PostObjectV4:
$postObject = new \Aws\S3\PostObjectV4(
$client,
$this->bucketName,
$formInputs,
$options,
$expires
);
However, when the file is uploaded, while it appears in the right folder it is named {$filename}. I think I've been consistent with the documentation around the key, which states:
To use the file name provided by the user, use the ${filename} variable. For example, if the user Betty uploads the file lolcatz.jpg and you specify /user/betty/${filename}, the key name will be /user/betty/lolcatz.jpg.
Can anyone let me know what I'm doing wrong here?
/ Jonathan
Hi !
What you want here is likely restricting user upload so that a given user is only allowed to post files into a sub-folder in your S3 bucket (for instance if your user is "foo", you want him to upload only files under the "foo/" path).
This is what I do:
$conditions = [
['acl' => 'public-read'],
['bucket' => $s3Bucket],
['starts-with', '$key', $username . '/']
];
$postSigner = new PostObjectV4($s3Client, $s3Bucket, [], $conditions, '+7 days');
You can see that the correct thing is "starts-with", not "key". Then, it's up to you, in the HTML where you upload the file (either through a hidden field, or with an Ajax call), to add the "key" attribute, that will need to start by the given key you've indicated in the starts-with condition.
As far as I know there is no way to specify a prefix when generating the signature, and then having the prefix automatically appended when you upload the file: you'll need to make sure to specify it in the HTML attribute.
Thanks for the reply @bakura10!
I think I've left out too much detail in my original post. Here is the $conditions array I was using:
$options = [
['acl' => 'public-read'],
['bucket' => $this->bucketName],
['starts-with', '$key', 'activity/'],
];
It's pretty much the same as yours. The $formInputs I specified and passed into the third parameter of PostObjectV4. I then pass them to my form (alongwith any other hidden inputs):
$this->formInputs = $postObject->getFormInputs();
I then print $this->formInputs out as hidden inputs in my form:
(I've removed all the input values except for "key", for clarity)
<input type="hidden" name="acl" value="">
<input type="hidden" name="key" value="activity/{$filename}">
<input type="hidden" name="X-Amz-Credential" value="">
<input type="hidden" name="X-Amz-Algorithm" value="">
<input type="hidden" name="X-Amz-Date" value="">
<input type="hidden" name="Policy" value="">
<input type="hidden" name="X-Amz-Signature" value="">
So I've included the key with the right prefix in the form, alongwith the {$filename} variable.
Is there any reason activity/{$filename} is the resulting object name? Am I perhaps putting the {$filename} variable in the wrong place?
Thanks for the help.
That's strange... it works here (although I'm uploading the image through an Ajax call).
I can see though that what is sent in Ajax call is indeed "username/{$filename}" as well. However, when I check the S3 bucket and the file, S3 autoamtically replaced it with the filename.
If you're uploading it using Ajax, did you make sure that you're properly sending this boundary in the payload ?
Content-Disposition: form-data; name="file"; filename="your_filename.png"
I'm doing a direct form post to S3, and S3 is redirecting me back to the form after it completes.
That seems to work fine, except for the name of the resulting object.
I should also note that if I am uploading the file to the root folder of the bucket (without the /activity), the filename appears correct.
Is there anything obviously wrong with the form?
(input values removed for brevity and replaced the bucketname with <
<form role="form" method="post" action="https://<bucketname>.s3.amazonaws.com" enctype="multipart/form-data">
<input type="hidden" name="acl" value="">
<input type="hidden" name="key" value="activity/{$filename}">
<input type="hidden" name="X-Amz-Credential" value="">
<input type="hidden" name="X-Amz-Algorithm" value="">
<input type="hidden" name="X-Amz-Date" value="">
<input type="hidden" name="Policy" value="">
<input type="hidden" name="X-Amz-Signature" value="">
<div class="form-group">
<label for="" class="control-label">
Choose an image to upload </label>
<input type="file" name="file" size="40">
</div>
Everything seems correct to me :/. The only difference between your code and mine is that I pass an empty array as third parameters while you do pass form inputs (I generate them manually in the HTML). But I don't think this can have any impact at all...
Sorry :(. I'll let someone from AWS answering you!
Oh MY GOSH.
It's ${filename} not {$filename}. :)
Thanks @bakura10
I'm going to go hide in a hole of shame...
Oh... i should have spot it :d. I know way too much that kind of "issue"... :D