Posting and Getting files in ruby/rails
Today I’m going to show some very short snippet about posting files with ruby, and receiving them in a rails controller.
For all examples I’ll be using the rest-client gem (”sudo gem install rest-client”).
The fist thing we’re going to do is to implement a very basic file post in ruby - there is basically two methods:
- You can post the contents of the file straight to the request body (I’m going to call it the “raw way”);
- You can pass the file contents as a parameter inside your request, like any other (I’m going to call it the “pretty way”).
One method is not necessarily better than the other, how you should do it depends a lot more on how your target service is implemented.
Posting a file, the “pretty way”:
PRETTY_UPLOAD = "http://localhost:3000/files/upload_pretty/pretty_file.txt"
def self.post
pretty_resource = RestClient::Resource.new PRETTY_UPLOAD
pretty_file = "./pretty_file.txt"
File.open pretty_file, "wb" do |file|
file.write "some random pretty content"
end
pretty_resource.post :file => File.read(pretty_file)
end
Posting a file, the “raw way”:
RAW_UPLOAD = "http://localhost:3000/files/upload_raw/raw_file.txt"
def self.post
raw_resource = RestClient::Resource.new RAW_UPLOAD
raw_file = "./raw_file.txt"
File.open raw_file, "wb" do |file|
file.write "some random raw content"
end
raw_resource.post File.read(raw_file)
end
Now, getting a file - since there is basically just one way to get it, I’ve made just one method - getting a file on ruby:
DOWNLOAD = "http://localhost:3000/files/download/raw_file.txt"
def self.get
resource = RestClient::Resource.new DOWNLOAD
downloaded_file = "./downloaded_file.txt"
response = resource.get
# you can access the headers (response.headers) or the
# http response (response.net_http_res) if you need to
File.open downloaded_file, "wb" do |file|
file.write response.to_s
end
end
That’s pretty much all you need on the client side (reading the contents of a regular http request should be no different at all than reading an attached file).
Time to go to the server side, shall we? Here good old rails kicks ass per se.
All I needed to do was to set up a custom route (just to make things more clear):
map.files ':controller/:action/:name.:extension'
Then, for the controller, I’ve set up two methods to receive the posted file - pay attention to the slightly different approach for the “pretty way” and the “raw way” of posting a file.
Receiving a file, the “pretty way”:
def upload_pretty
file_name = "#{params[:name]}.#{params[:extension]}"
file_contents = params[:file]
File.open "tmp/#{file_name}", "wb" do |file|
file.write file_contents
end
render :text => "ok"
end
Receiving a file, the “raw way”:
def upload_raw
file_name = "#{params[:name]}.#{params[:extension]}"
file_contents = request.raw_post
File.open "tmp/#{file_name}", "wb" do |file|
file.write file_contents
end
render :text => "ok"
end
I also provided a method for the client to download back the files, so that you can check on the contents to see that it went through flawlessly:
def download
file_name = "#{params[:name]}.#{params[:extension]}"
send_file "tmp/#{file_name}"
# you can also use: send_data File.read("tmp/#{file_name}")
end
And that’s basically it, as simple as it can be.
As usual, you can download the sample code clicking here.
That’s a very quickly put together piece of code which, most likely, can be greatly improved - but I think it is just good enough to show the basics of how to get and post files on ruby and rails.
Criticism is always welcome.
Tags: download, file, get, http, post, rails, request, response, rest, restful, routes, Ruby, upload, web