Rails Active Storage: how to access file contents before it has been saved

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Rails Active Storage: how to access file contents before it has been saved

Nerdture
I am working on building an API front end for a 3rd Party API.  In addition to collecting the file from my user, I also need to post the file to the 3rd Party Service.

The only way I have been able to get the actual file contents is to download it again after it has been saved.

class Template < ApplicationRecord
    has_one_attached
:pv_file
...
    post_body
<< self.pv_file.blob.download

I want to have a before create filter that throws an error if the 3rd Party API rejects the file (e.g. wrong format, service unavailable, etc), but the only way I have found to access the file content is by downloading it again.

How can we access the actual file content before it has been saved and uploaded?

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-core/808b4f3c-fa98-4624-91ce-d55f934c56b0%40googlegroups.com.
Reply | Threaded
Open this post in threaded view
|

Re: Rails Active Storage: how to access file contents before it has been saved

Mladen Ilic
Hi Nerdture,

I'm not a core team member, but I believe that there's currently no documented way of accessing a file before the record has been saved (more precisely, before the after_commit callback). There is, however, `attachment_changes` hash, which keeps track of what changes are made. You should be able to access the attachment with `record.attachment_changes['pv_file']`. Keep in mind that this is undocumented internal api, so it could change in the future.

On Wednesday, December 4, 2019 at 2:05:50 PM UTC+1, Nerdture wrote:
I am working on building an API front end for a 3rd Party API.  In addition to collecting the file from my user, I also need to post the file to the 3rd Party Service.

The only way I have been able to get the actual file contents is to download it again after it has been saved.

class Template < ApplicationRecord
    has_one_attached
:pv_file
...
    post_body
<< self.pv_file.blob.download

I want to have a before create filter that throws an error if the 3rd Party API rejects the file (e.g. wrong format, service unavailable, etc), but the only way I have found to access the file content is by downloading it again.

How can we access the actual file content before it has been saved and uploaded?

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-core/23d9ce5f-1b4c-4217-b7f1-4d5ab2ea5783%40googlegroups.com.
Reply | Threaded
Open this post in threaded view
|

Re: Rails Active Storage: how to access file contents before it has been saved

Nerdture
Thanks Mladen Ilic for your reply.  

I think I am getting closer to the solution I need.

You should be able to access the attachment with `record.attachment_changes['pv_file']`. 

I must be doing something wrong, as I can't figure out how to access the actual file contents/octet-stream.

post_body << self.attachment_changes['pv_file']
throws Zlib::Data Error incorrect header check

post_body << self.attachment_changes['pv_file'].blob.download
throws Aws::S3::Errors::NoSuchKey

post_body << self.attachment_changes['pv_file'].blob.open
throws ActiveStorage::FileNotFoundError

I am sure I am showing my Ruby ignorance here.

Any help is appriciated.

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-core/38ecc9f7-adae-4571-8729-66fb5bf2c316%40googlegroups.com.
Reply | Threaded
Open this post in threaded view
|

Re: Rails Active Storage: how to access file contents before it has been saved

Mladen Ilic
Hi again Nerdture,

According to the implementation of ActiveStorage::Attached::Changes::CreateOne, you should be able to access instance of ActionDispatch::Http::UploadedFile with following:
self.attachment_changes['pv_file'].attachable

In you examples, you are trying to download file from a storage service to a tempfile before it has been uploaded, so storage service fails to locate it.

Best,
On Wednesday, December 4, 2019 at 7:53:03 PM UTC+1, Nerdture wrote:
Thanks Mladen Ilic for your reply.  

I think I am getting closer to the solution I need.

You should be able to access the attachment with `record.attachment_changes['pv_file']`. 

I must be doing something wrong, as I can't figure out how to access the actual file contents/octet-stream.

post_body << self.attachment_changes['pv_file']
throws Zlib::Data Error incorrect header check

post_body << self.attachment_changes['pv_file'].blob.download
throws Aws::S3::Errors::NoSuchKey

post_body << self.attachment_changes['pv_file'].blob.open
throws ActiveStorage::FileNotFoundError

I am sure I am showing my Ruby ignorance here.

Any help is appriciated.

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-core/deb73d0c-22c5-4187-8838-99b94820e43c%40googlegroups.com.
Reply | Threaded
Open this post in threaded view
|

Re: Rails Active Storage: how to access file contents before it has been saved

Nerdture
Thanks again Mladen Ilic for your help.

For anyone that finds this, in order to build the multipart form-data, I needed to use the following to get the Octet-stream.

post_body << self.attachment_changes['pv_file'].attachable.read

Hopefully we will eventually get a permanent/documented way to access the data pre-save.


--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-core/60f5cdae-bff3-4a49-bec1-89b6c54a1c0f%40googlegroups.com.