2011-05-17 64 views
6

我想上傳我在Ruby中運行時生成的數據,就像從塊中提供上傳數據一樣。我如何在Ruby中從內存中發佈流數據?

我發現的所有示例僅顯示如何在請求之前流式傳輸必須位於磁盤上的文件,但我不想緩衝該文件。

除了滾動我自己的套接字連接之外,最好的解決方案是什麼?

這個僞代碼示例:

post_stream('127.0.0.1', '/stream/') do |body| 
    generate_xml do |segment| 
    body << segment 
    end 
end 

回答

1

有一個網:: HTTPGenericRequest#body_stream =(obj.should的respond_to(?:讀))

您可以使用它或多或少是這樣的:


class Producer 
    def initialize 
    @mutex = Mutex.new 
    @body = '' 
    end 

    def read(size) 
    @mutex.synchronize { 
     @body.slice!(0,size) 
    } 
    end 

    def produce(str) 
    @mutex.synchronize { 
     @body << str 
    } 
    end 
end 

# Create a producer thread 

req = Net::HTTP::Post.new(url.path) 
req.body_stream = producer 
res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) } 
+0

第二個想法,也許互斥體不是最好的方法,因爲你可能想要阻止,而EOF沒有達到。但是線程編程是一個不同的故事。檢查http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_threads.html – Roman 2011-05-17 10:54:57

+0

好吧,很高興聽到它適合你!請將此答案標記爲「已接受」,然後:) – Roman 2011-05-17 12:26:15

2

有效的代碼。

require 'thread' 
    require 'net/http' 
    require 'base64' 
    require 'openssl' 

    class Producer 
     def initialize 
     @mutex = Mutex.new 
     @body = '' 
     @eof = false 
     end 

     def eof!() 
     @eof = true 
     end 

     def eof?() 
     @eof 
     end 

     def read(size) 
     @mutex.synchronize { 
      @body.slice!(0,size) 
     } 
     end 

     def produce(str) 
     if @body.empty? && @eof 
      nil 
     else 
      @mutex.synchronize { @body.slice!(0,size) } 
     end 
     end 
    end 

    data = "--60079\r\nContent-Disposition: form-data; name=\"file\"; filename=\"test.file\"\r\nContent-Type: application/x-ruby\r\n\r\nthis is just a test\r\n--60079--\r\n" 

    req = Net::HTTP::Post.new('/') 
    producer = Producer.new 
    req.body_stream = producer 
    req.content_length = data.length 
    req.content_type = "multipart/form-data; boundary=60079" 

    t1 = Thread.new do 
     producer.produce(data) 
     producer.eof! 
    end 

    res = Net::HTTP.new('127.0.0.1', 9000).start {|http| http.request(req) } 
    puts res 
+0

添加示例:) – Roman 2011-05-17 09:19:36

+0

謝謝。我添加了一些幾乎可以工作的代碼,但是代碼末尾的Net:HTTP代碼行永遠不會返回。有什麼建議麼? – Sam 2011-05-17 10:55:51

+0

當你決定沒有什麼需要發送的時候,你必須返回零。生產/消費業務邏輯通常是這樣的:「是eof到達了?如果是,如果不是,那麼是否有東西要發送? - 發送,否則在等待數據時阻塞」。檢查條件變量 - http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_threads.html#UF – Roman 2011-05-17 11:22:02