Reputation: 97
I have a file coming into my rails app from another website. The POST data looks like this:
Parameters: {"file"=>#<ActionDispatch::Http::UploadedFile:0x007fa03cf0c8d0 @original_filename="Georgia.svg", @content_type="application/octet-stream", @headers="Content-Disposition: form-data; name=\"file\"; filename=\"Georgia.svg\"\r\nContent-Type: application/octet-stream\r\n", @tempfile=#<File:/var/folders/g0/m3jlqvpd4cbc3khznvn5c_7m0000gn/T/RackMultipart20130507-52672-1sw119a>>, "originalFileName"=>"Georgia.ttf"}
My controller code is this:
def target
@incoming_file = params[:file]
file_name = params[:originalFileName]
File.open("/Users/my_home_directory/#{file_name}", "w+b") {|f| f.write(@thing)}
end
Right now, I can create a file on my hard drive that contains a line of text that shows the object.
This is the code from the file created in my hard drive.
<ActionDispatch::Http::UploadedFile:0x007fa03cd1c318>
I can write a file with the name of the uploaded file. I can't seem to figure out how to write the data from the file to my drive. I'm new to ruby on rails. Help me see what I'm missing. Thx.
Upvotes: 3
Views: 6257
Reputation: 484
Obvious solution would be the one suggested by Richie Min, but it is a bad solution in terms of memory usage, which might get critical if you start uploading large files. Since
File.open(...) {|f| f.write(@incoming_file.read)}
reads whole uploaded file in memory with @incoming_file.read
. Better option would be:
def target
@incoming_file = params[:file]
file_name = params[:originalFileName]
FileUtils.mv @incoming_file.tempfile, "/Users/my_home_directory/#{file_name}"
end
Uploaded data is always stored in temporary files, and UploadedFile.read
is actually just a proxy to actual File object, which is accessible trough UploadedFile.tempfile
. This, however, could also be not the best solution if temporary folder and destination directory are on different partitions or even on different disk drives, but still much better than reading the whole file in memory in Rails controller.
You can test it with:
curl -X POST -F file=@[some large file] -F originalFileName=somefilename.ext http://[your url]
Upvotes: 16
Reputation: 654
use
File.open("/Users/my_home_directory/#{file_name}", "w+b") {|f| f.write(@incoming_file.read)}
Upvotes: 1