dwilkie / carrierwave_direct

Process your uploads in the background by uploading directly to S3
MIT License
839 stars 181 forks source link

Can I still upload a file from code in Rails? #233

Closed founder3000 closed 4 years ago

founder3000 commented 4 years ago

I use this gem for file uploads from our UI. But I have a use case for grabbing files from a remote SFTP server and creating them as Uploads (Upload is an AR object).

Upload mounts an Uploader object like so:

  mount_uploader :text_file_name, TextFileUploader

Then I try this:

upload = user.uploads.new
upload.text_file_name = File.open('myfile.csv')
upload.save!

I was always getting:

ActiveRecord::RecordInvalid (Validation failed: Text file name is invalid. )

like that. So I turned off filename formatting in the initializer:

  CarrierWave.configure do |config|
    config.validate_filename_format = false        # defaults to true

Now my upload works, but the file name is being changed to text_file_name.

I'm not sure why the validation step is being used to set the file name. I'm worried that turning this off will also screw up the names in the UI upload.

UPDATE

Yeah that's not going to work either. It saves the file with no name on S3. Here is an example download link:

https://mybucket.s3.amazonaws.com/upload/text_file_name/upload/text_file_name?X-Amz-Expires=600&X-Amz-Date=20200703T135637Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJJ5W4XTT5QFTXMWA%2F20200703%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-SignedHeaders=host&X-Amz-Signature=29ce0453757d69a13eb4090907347875734acfe475f0b4fc4b170f62f2054e3d

Now this download link DOES work. I'm not sure how, because there's no file name. Here's what a "healthy" link using S3 looks like:

https://mybucket.s3.amazonaws.com/upload/text_file_name/ca85e094-189d-48a2-835b-d3ae0e50b15d/<file-name.csv>?X-Amz-Expires=600&X-Amz-Date=20200703T135817Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJJ5W4XTT5QFTXMWA%2F20200703%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-SignedHeaders=host&X-Amz-Signature=556c3ce5fce7c994c611623745bf5c36b3dfff86aa9c5b3660e743434246466b

The area after text_file_name holds the S3 key normally.

founder3000 commented 4 years ago

I figured it out by observing the behavior of the form.

filename = 'myfile.csv'
upload = user.uploads.new
key = upload.text_file_name_key.gsub('${filename}', filename)
upload.text_file_name = File.open(filename)
upload.text_file_name_key = key
upload.save!

Works!