Reading body stream in Sinatra

2019-08-30 03:40发布

I'm trying to upload a file with XHR request using PUT method with Sinatra. My first idea was to upload the file and writing the stream directly into a MongoDB GridFS

@fs.open("test.iso", "w") do |f|
  f.write request.body.read
end 

It works, but, it loads the entire file into the RAM and it write it into the MongoDB GridFS. I'd like to avoid this behavior by writing it continuously to the GridFS (stream the file, not loading it and put it in the GridFS) without loading the entire file into the RAM : because for huge files (like 1GB or more) it's clearly a bad practice (due to RAM consumption).

How can I do that ?

EDIT : Can I have Sinatra / Rack not read the entire request body into memory? method is creating a TempFile, the thing is I want to only work with streams to optimize memory consumption on server-side. Like a php://input would do in PHP.

EDIT 2 :

Here is how I'm currently handling it :

标签: ruby sinatra
1条回答
成全新的幸福
2楼-- · 2019-08-30 03:41

It looks like the streaming support in Sinatra is only in the opposite direction for long running GET requests out to the client.

If you do a POST multipart upload, Sinatra will write the data to a tempfile and provide you with the details in the params Hash.

require 'sinatra'
require 'fileutils'

post '/upload' do
  tempfile = params['file'][:tempfile]
  filename = params['file'][:filename]
  FileUtils.mv(tempfile.path, "test.iso")
  "posted"
end

While in the same sinatra directory:

$ echo "testtest" > /tmp/file_to_upload
$ curl --form "file=@/tmp/file_to_upload" http://localhost:4567/upload
posted
$ cat test.iso
testtest
查看更多
登录 后发表回答