lib/merb/mixins/controller_mixin.rb in merb-0.2.0 vs lib/merb/mixins/controller_mixin.rb in merb-0.3.0

- old
+ new

@@ -9,16 +9,17 @@ boundary = "--#{boundary}" paramhsh = MerbHash.new buf = "" content_length = @env['CONTENT_LENGTH'].to_i input = request + input.binmode if defined? input.binmode boundary_size = boundary.size + EOL.size bufsize = 16384 content_length -= boundary_size status = input.read(boundary_size) raise EOFError, "bad content body" unless status == boundary + EOL - rx = /(?:#{EOL})?#{Regexp.quote(boundary)}(#{EOL}|--)/ + rx = /(?:#{EOL})?#{Regexp.quote(boundary,'n')}(#{EOL}|--)/ loop { head = nil body = '' filename = content_type = name = nil @@ -30,11 +31,11 @@ filename = head[FILENAME_REGEX, 1] content_type = head[CONTENT_TYPE_REGEX, 1] name = head[NAME_REGEX, 1] - if filename + if filename && !filename.empty? body = Tempfile.new(:Merb) body.binmode if defined? body.binmode end next end @@ -56,13 +57,18 @@ buf.slice!(0, boundary_size+2) content_length = -1 if $1 == "--" end - if filename + if filename && !filename.empty? body.rewind - data = {:filename => filename, :type => content_type, :tempfile => body} + data = { + :filename => File.basename(filename), + :content_type => content_type, + :tempfile => body, + :size => File.size(body) + } else data = body end paramhsh = normalize_params(paramhsh,name,data) break if buf.empty? || content_length == -1 @@ -88,11 +94,11 @@ # parses a query string or the payload of a POST # request into the params hash. So for example: # /foo?bar=nik&post[title]=heya&post[body]=whatever # parses into: - # {:bar => 'nik', :post => {:title => 'heya', :body => 'whatever}} + # {:bar => 'nik', :post => {:title => 'heya', :body => 'whatever'}} def query_parse(qs, d = '&;') m = proc {|_,o,n|o.u(n,&m)rescue([*o]<<n)} (qs||'').split(/[#{d}] */n).inject(MerbHash[]) { |h,p| k, v=unescape(p).split('=',2) h.u(k.split(/[\]\[]+/).reverse. @@ -159,9 +165,32 @@ 'X-SENDFILE' => file ) return end + # stream_file( { :filename => file_name, + # :type => content_type, + # :content_length => content_length }) do + # @response.send_status(opts[:content_length]) + # @response.send_header + # AWS::S3::S3Object.stream(user.folder_name + "-" + user_file.unique_id, bucket_name) do |chunk| + # @response.write chunk + # end + # end + def stream_file(opts={}, &stream) + opts.update(Merb::Const::DEFAULT_SEND_FILE_OPTIONS.merge(opts)) + disposition = opts[:disposition].dup || 'attachment' + disposition << %(; filename="#{opts[:filename]}") + @response.headers.update( + 'Content-Type' => opts[:type].strip, # fixes a problem with extra '\r' with some browsers + 'Content-Disposition' => disposition, + 'Content-Transfer-Encoding' => 'binary', + 'CONTENT-LENGTH' => opts[:content_length] + ) + stream + end + + # This uses nginx X-Accel-Redirect header to send # a file directly from nginx. See the nginx wiki: # http://wiki.codemongers.com/NginxXSendfile def nginx_send_file(file) headers['X-Accel-Redirect'] = File.expand_path(file) \ No newline at end of file