代码之家  ›  专栏  ›  技术社区  ›  taro

如何使用Ruby通过HTTP下载大文件

  •  5
  • taro  · 技术社区  · 15 年前

    我只需要通过HTTP下载文件的前几千字节。

    我试过

    require 'open-uri'
    url = 'http://example.com/big-file.dat'
    file = open(url)
    content = file.read(limit)
    

    但它实际上下载了完整的文件。

    3 回复  |  直到 11 年前
        1
  •  4
  •   Michel de Graaf    15 年前

    使用插座时,这似乎有效:

    require 'socket'                  
    host = "download.thinkbroadband.com"                 
    path = "/1GB.zip" # get 1gb sample file
    request = "GET #{path} HTTP/1.0\r\n\r\n"
    socket = TCPSocket.open(host,80) 
    socket.print(request)        
    
    # find beginning of response body
    buffer = ""                    
    while !buffer.match("\r\n\r\n") do
      buffer += socket.read(1)  
    end           
    
    response = socket.read(100) #read first 100 bytes of body
    puts response
    

    我很好奇是否有“红宝石之路”。

        2
  •  4
  •   zed_0xff    11 年前

    这是一条古老的线索,但根据我的研究,这仍然是一个几乎没有答案的问题。下面是我提出的一个解决方案,猴子补丁net::http一点:

    require 'net/http'
    
    # provide access to the actual socket
    class Net::HTTPResponse
      attr_reader :socket
    end
    
    uri = URI("http://www.example.com/path/to/file")
    begin
      Net::HTTP.start(uri.host, uri.port) do |http|
        request = Net::HTTP::Get.new(uri.request_uri)
        # calling request with a block prevents body from being read
        http.request(request) do |response|
          # do whatever limited reading you want to do with the socket
          x = response.socket.read(100);
        end
      end
    rescue IOError
      # ignore
    end
    

    当您过早调用http.finish时,rescue会捕获抛出的ioerror。

    仅供参考, HTTPResponse 对象不是真的 IO 对象(它是一个名为 BufferedIO 但是,很容易猴补丁,也可以模仿 输入输出 你需要的方法。例如,我使用的另一个库(exifr)需要 readchar 方法,很容易添加:

    class Net::BufferedIO
      def readchar
        read(1)[0].ord
      end
    end
    
        3
  •  0
  •   the Tin Man    12 年前

    退房 OpenURI returns two different objects “。您可能会滥用其中的方法,在预设限制后中断下载/丢弃结果的其余部分。