How to attach files, which were saved in DriveHQ in Rails mailer? - ruby-on-rails

In my application i have a file upload option. The uploaded files used to saved in DriveHQ ftp server. After uploading i want to send a mail to the admin with the uploaded file as attachment.
I tried as follows
uri = URI::FTP.build(['username:password', 'ftp.drivehq.com', nil,"\\My Documents\\#{17}\\Fitness.txt", 'i'])
And in the mailer:
attachments['image'] = {mime_type: 'text/plain',content: File.read(uri)}
But its not working. it was returning error as
bad component(expected relative path component): \My Documents\17\Fitness.txt;type=i

I guess you're using the API in a wrong way.
You need to download the file, and yes you do it by creating an URI to the FTP server, but then you need to download the file to a temporary directory.
After that, in your mailer you read that file.
Remember since File is a subclass of IO and it does not have the read method, when you invoke File.read, you are actually calling IO.read.

Related

MVC: when is a file uploaded?

When uploading files to a server and calling a controller method does a HttpPostedFileBase contain the entire file or just information such as name, path, etc?
What I want to know is if the file is uploaded to the server right away or not until calling SaveAs(path) ?
As the file is part of your request, it is uploaded immediatly. It is just buffered into a tempfile which the system will delete once you send the Response.
If you use SaveAs, you just transfert the file into a permanent location.

How do you create a file without touching the hard disk?

I'm trying to create PDFs that can be stored on an external server.
I do this:
File.new("temp.pdf", "w").close
File.open("temp.pdf", "wb") do |f|
f.write(bytes)
end
File.open("temp.pdf", "r") do |f|
# upload `f` to server
end
File.delete("temp.pdf")
then upload them to the server.
On my local machine this works fine, but, I recently tried running on another machine, and I got a permissions error in the log.
Is there a way to:
Write bytes to a file.
Never touch the hard disk.
Why don't you just upload the bytes to the server?
You may have to go a little lower-level than normal, but check for instance the UploadIO class of the multipart-post gem.
I realize I have to write to file and delete the file since UploadIO takes in an open file
So I created an new file, wrote the content to it, passed it in as a File.open to UploadIO, and then deleted the file after I send it.

Carrierwave + Fog(s3). Letting the users to download the file

I am working on a project where I have to provide download links to user for the files which are stored in the s3. Initially I tried,
link_to "Download", #medium.file.url
But this opens the file directly on the browser. When i tried to download an mp4 file, chrome started playing it automatically. I don't want that to happen. So I am using send_file for this task,
def download
#medium = Medium.find(params[:id])
send_file #medium.file.url
end
In my local, I have set the storage to file and I have tested this, which works perfectly fine. But on staging, the files are served from s3, I am always getting ActionController::MissingFile. My app is hosted on heroku. I also want to know if using send_file is good choice or if there is a better way of doing this.
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
When i was googling, i found that nginx header setting for sending files should be enabled for production. I added the following line in config/environments/production.rb. Still no luck. I need some help on this. Thanks.
I think this is because S3 wants the file to be played.
I don't have access to my S3 here, but I solved the problem by changing the action for PDF files (which was shown my case) in the S3 control panel.
If you can fix this, I think you can avoid using send_file completely.
Edit: I managed to access S3 now. Go to properties -> Metadata, and add the key
Content-Disposition: Attachment
Then your file will always be downloaded instead of shown.

Downloading files from Paperclip

I have a controller action that is meant to send a file to the user for download from my bucket in S3.
Here's the controller code:
send_file #project.file.url, :type => #project.file_content_type
Here's the error:
Cannot read file http://s3.amazonaws.com/bucket/projects/1/project.xlsx?2011
When I go to the URL directly, I get a download of the file! What's going on?
Is it ok if you just redirect the user to the file on S3?
redirect_to #project.file.url
The issue is that send_file expects a path to a local file, which is then used by the webserver to serve up data from the local file it can access on disk. The file on S3 is only accessible by HTTP, so your webserver can't serve it. To use send_file you'd have to download it and then serve it I think.

Alternative to X-sendfile in Apache for sending file given a URL?

I'm writing a Rails application that serves files stored on a remote server to the end user.
In my case the files are stored on S3 but the user requests the file via the Rails-application (hiding the actual URL). If the file was on my servers local file-system, I could use the Apache header X-Sendfile to free up the Ruby process for other requests while Apache took over the task of sending the file to the client. But in my case - where the file is not on the local file-system, but on S3 - it seems that I'm forced to download it temporarily inside Rails before sending it to the client.
Isn't there a way for Apache to serve a "remote" file to the client that is not actually on the server it self. I don't mind if Apache has to download the file for this to work, as long as I don't have to tie up the Ruby process while it's going on.
Any suggestions?
Thomas, I have similar requirements/issues and I think I can answer your problem. First (and I'm not 100% sure you care for this part), hiding the S3 url is quite easy as Amazon allows you to point CNAMES to your bucket and use a custom URL instead of the amazon URL. To do that, you need to point your DNS to the correct amazon URL. When I set mine up it was similar to this: files.domain.com points to files.domain.com.s3.amazonaws.com. Then you need to create the bucket with the name of your custom URL (files.domain.com in this example). How to call that URL will be different depending on which gem you use, but a word of warning was that the attachment_fu plugin I was using was incorrectly sending me to files.domain.com/files.domain.com/name_of_file.... I couldn't find the setting to fix it, so a simple .sub method for the S3 portion of the plugin fixed it.
On to your other questions, to execute some rails code (like recording the hit in the db) before downloading you can simply do this:
def download
file = File.find(...
# code to record 'hit' to database
redirect_to 3Object.url_for(file.filename,
bucket,
:expires_in => 3.hours)
end
That code will still cause the file to be served by S3, but and still give you the ability to run some ruby. (Of course the above code won't work as is, you will need to point it to the correct file and bucket and my amazon keys are saved in a config file. The above is also using the syntax for the AWS::S3 gem - http://amazon.rubyforge.org/).
Second, the Content-Disposition: attachment issue is a bit more tricky. Hopefully, your situation is a bit more simple than mine and the following solution can work. Assuming the object 'file' (in this example) is the correct S3 object, you can set the disposition to attachment by
file.content_disposition = "attachment"
file.save
The above code can be executed after the file exists on the S3 server (unlike some other headers and permissions), which is nice and it can also be added when you upload the file (syntax depends on your plugin). I'm still trying to find a way to tell S3 to send it as an attachment and only when requested (not every time), and if you find that, please let me know your solution. I need to be able to sometimes download it and other times save embed images (for example) into HTML. I'm not using the above mentioned redirect but fortunately it seems that if you embed (such as a HTML image tag) a file with the content-disposition/attachment header, and the browser still displays the image normally (but I haven't throughly tested that across enough browsers to send it in the wild).
Hope that helps! Good luck.

Resources