To start, I'm using ruby's aws-sdk, but what I'm facing seems to be a misunderstanding of S3's presigned posts.
What I want to be able to do is ensure that anything uploaded to S3 with my presigned post is a video.
What I've tried doing is setting content_type_starts_with: "video/"
in the presigned_post hash. This causes all uploads to be rejected with Policy Condition failed: ["starts-with", "$Content-Type", "video/"]
.
I then tried just content_type: "video/mp4"
, but this causes s3 to allow any file to be uploaded, and then just tags it with Content-Type: "video/mp4"
in the metadata.
I then noticed that when I upload a file without a Content-Type constraint, S3 will tag the file as binary/octet-stream
. So I tried the first method again, but this time with content_type_starts_with: "binary/"
. Same results as before, Policy Condition Failed
.
How am I supposed to use the Content-Type field? It does't seem to ever do what I want it to do.
Here's a snippet of the code I'm using:
# In the controller
client = Aws::S3::Client.new(region: 'us-east-1')
resource = Aws::S3::Resource.new(client: client)
bucket = resource.bucket("my-bucket")
object_id = SecureRandom.uuid
object = bucket.object(object_id)
@presigned_post = object.presigned_post({
acl: "private",
content_length_range: 0..104857600, # 100 MB
content_type_starts_with: "video/",
})
# In the presigned post erb
<form action="<%= presigned_post.url %>" method="post" enctype="multipart/form-data">
<% presigned_post.fields.each do |name, value| %>
<input type="hidden" name="<%= name %>" value="<%= value %>"/>
<% end %>
<input type="file" name="file" accept="*.mp4,*.ogg,video/*" />
<input type="submit">
</form>