Using Rails 6 and CarrierWaveDirect, we're able to successfully POST a file to a presigned S3 URL, but then we encounter an error when trying to download the file from S3 to our server for processing.
Our model and uploader look like this:
# model
class FileAttachment < ApplicationRecord
mount_uploader :file, FileUploader
end
# uploader
class FileUploader < CarrierWave::Uploader::Base
include CarrierWaveDirect::Uploader
end
S3 responds to our direct uploads (POST) as expected with something like this:
{
"bucket" => "my-bucket",
"key" => "uploads/abcde-my-file.pdf",
"etag" => "12345"
}
Following the docs, we handle the response by saving the returned key
attribute to a new model like so:
@file_attachment = FileAttachment.new file_key: params[:key]
@file_attachment.save
This seems to work fine, however, when it tries to download the file from S3 to our server for processing, that fails due to a 400 Bad Request:
irb(main)> @file_attachment.remote_file_url = @file_attachment.file.url
=> "https://my-bucket.s3-us-west-2.amazonaws.com/uploads/abcde-my-file.pdf?X-Amz-Expires=600&X-Amz-Date=20211009T202903Z&X-Amz-Algorithm=...&X-Amz-Credential=...&X-Amz-SignedHeaders=host&X-Amz-Signature=..."
irb(main)> @file_attachment.save
=> false
irb(main)> @file_attachment.errors.full_messages
=> ["File could not download file: 400 Bad Request"]
Despite the 400, I can confirm that @file_attachment.file.url
is a valid, working URL, and when accessing the URL through a browser, the file is able to be downloaded just fine. For some reason though, it can't be downloaded from our app.
Can anyone spot what we're doing wrong? Or does anyone know of a better way to debug this ("400 Bad Request" isn't enough information). Thanks in advance!
Here's our bucket CORS:
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET",
"POST",
"PUT"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": []
}
]
And our environment details:
ruby '2.7.2'
gem 'rails', '~> 6.0.3'
gem 'carrierwave', '~> 2.1.0'
gem 'carrierwave_direct', '~> 2.1.0'
Thanks in advance!