This question is for anyone who has experience with the Ruby Gem Shrine for File Uploads.
I am trying to scan file uploads for viruses using ClamAV. The scan works well however the file is already auto uploaded to cloud storage by Shrine prior to validation.
- Is there a hook/callback in Shrine we can use to run the scan prior to file is uploaded?
- Is there are an alternative approach?
Here is the code at the moment.
Attacher.validate do
if file
tmp_file = file.download
# raise Services::Clamav::Client::FileContainVirus
errors << "virus file" if Services::Clamav::Client.virus?(tmp_file.path)
end
end
Any thoughts/answers will help. Thank you.
First, note about uploading files through Shrine. All files first get uploaded to a cache/temporary storage (usually on local filesystem), and are persisted in the final storage only after validations pass. Thus, the validations you run are ran on the cached file, and if a virus (or other validation failure) is detected, it won't be promoted to the permanent storage. You can learn more about how this works in the Shrine Getting Started guide.
However, the documentation demonstrates custom validations like this:
The
add_metadatablocks are passed anioinstance that can be used to read the file stream, or it can be promoted to a file object usingShrine.with_file(io). You could achieve your goal by adding metadata:is_virus?and checking that upon validation. (Note that ClamAV actually supports streaming throughclamdscan --stream -, so you can directly use theioinstance instead of promoting to a file.)