Generate Presigned S3 URL in Ruby and Upload file

In this article, I have covered how to generate presigned S3 URL in Ruby. A presigned URL for an Amazon S3 bucket allows users to securely upload files directly to an S3 bucket without needing AWS credentials. This tutorial will guide you through the process of generating presigned S3 URLs in Ruby and demonstrate how to use these URLs to upload a file to an S3 bucket. By following step-by-step instructions, you can integrate this feature into your Ruby application swiftly.Generate PreSigned S3 URL

Table of Contents

Prerequisites

Before you begin, ensure you have the following set up:

  • An AWS account with access to S3.
  • The AWS SDK for Ruby installed in your application.
  • Your AWS access key, secret key, and an S3 bucket where the files will be uploaded.

Step-by-Step Instructions

Setting Up AWS SDK for Ruby

Start by configuring the AWS SDK. This entails setting up your AWS credentials and the region your bucket is in:

require 'aws-sdk-s3'

Aws.config.update({
  region: 'your-region',
  credentials: Aws::Credentials.new('your-access-key-id', 'your-secret-access-key')
})

 

Generating Presigned S3 URL in Ruby

To generate a presigned URL, you’ll need to define a function that takes the bucket name, the object key, and the link expiration time as parameters:

def generate_presigned_url(bucket_name, object_key, expiration_time = 3600)
  s3_client = Aws::S3::Client.new
  signer = Aws::S3::Presigner.new(client: s3_client)
  url = signer.presigned_url(:put_object, 
                      bucket: bucket_name, 
                      key: object_key,
                      expires_in: expiration_time)
  return url
end

Now call this function wherever you need to get a presigned URL:

bucket_name = 'your-bucket-name'
object_key = 'your/path/to/the/object'
expiration_time = 3600 # 1 hour

url = generate_presigned_url(bucket_name, object_key, expiration_time)
puts url

Output:

https://your-bucket-name.s3.amazonaws.com/your/path/to/the/object

 

Uploading a File Using the Presigned URL

After obtaining the presigned URL, you can make a PUT request to that URL to upload a file. Here is how you might perform this task using Ruby:

require 'net/http'

def upload_to_s3(presigned_url, file_path)
  uri = URI.parse(presigned_url)
  File.open(file_path, 'rb') do |file|
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = (uri.scheme == "https")
    request = Net::HTTP::Put.new(uri)
    request.body_stream = file
    request["Content-Type"] = "" # set appropriate content type if required
    response = http.request(request)
  end
end

# Example usage
upload_to_s3(url, 'path/to/your/local/file.ext')

Examples

Example 1: Generate a presigned URL that expires in two hours for a file ‘path/to/image.jpg’ in the ‘my-bucket’ bucket.

two_hour_expiration = 7200
image_url = generate_presigned_url('my-bucket', 'path/to/image.jpg', two_hour_expiration)
puts image_url

Output:

https://my-bucket.s3.amazonaws.com/path/to/image.jpg?X-Amz...

Troubleshooting Tips

  • If the presigned URL is not working, ensure the expiration time has not passed and the object key is correct.
  • Verify that you have the correct permissions set on your S3 bucket to allow for uploading objects.
  • Ensure the AWS region is correctly specified in your configuration, as it must match the region where your S3 bucket resides.
  • If uploads fail, check that you haven’t set the Content-Type header in your request unless it is necessary for your use case.

Conclusion

To sum up, you now know how to generate presigned S3 URLs in Ruby and upload files using these URLs. This method enhances security as it avoids exposing AWS credentials and limits access with an expiration time. Apply these techniques to enable secure, direct uploads to your S3 buckets within your Ruby applications. Remember to handle troubleshooting issues promptly, and experiment with different parameters to suit your needs.

References