检索图像的尺寸而无需下载整个图像

时间:2011-05-10 05:08:03

标签: ruby image io open-uri

我正在使用open-uri下载远程图像,然后使用imagesize gem来获取尺寸。问题是当需要处理少量图像时,这会变得非常缓慢。

如何下​​载足够的信息以了解各种图像格式的尺寸?

还有其他优化方法吗?

2 个答案:

答案 0 :(得分:2)

我相信如果你去原始套接字(发出简单的http请求),就不需要下载超过几个字节(并中止连接)来确定图像的尺寸。

require 'uri'
require 'socket'
raise "Usage: url [bytes-to-read [output-filename]]" if ARGV.length < 1
uri   = URI.parse(ARGV.shift)
bytes = (ARGV.shift || 50).to_i
file  = ARGV.shift
$stderr.puts "Downloading #{bytes} bytes from #{uri.to_s}"
Socket.tcp(uri.host, uri.port) do |sock|
  # http request
  sock.print "GET #{uri.path} HTTP/1.0\r\nHost: #{uri.host}\r\n\r\n"
  sock.close_write
  # http response headers
  while sock.readline.chomp != ""; end
  # http response body, we need first N bytes
  if file
    open(file,"wb") {|f| f.write(sock.read(bytes)) }
  else
    puts sock.read(bytes)
  end
end

e.g。如果我将PNG文件的前33个字节(GIF为13个字节)推入exiftool,它会给我图像大小

$ ruby download_partial.rb http://yardoc.org/images/ss5.png 33 | exiftool - | grep ^Image
Downloading 33 bytes from http://yardoc.org/images/ss5.png
Image Width                     : 1000
Image Height                    : 300
Image Size                      : 1000x300

答案 1 :(得分:0)

我不知道有任何方法可以指定使用普通HTTPd请求下载多少字节。这是一个全有或全无的情况。

某些文件类型确实允许文件的各个部分,但是,您必须控制服务器才能启用它。

我玩这个级别已经有很长一段时间了,但理论上你可以使用Net :: HTTP或Open-URI的块,并计算字节直到你收到适当的数字才能到达图像大小块,然后关闭连接。你的TCP堆栈可能对你不太满意,特别是如果你这么做的话。如果我没记错的话,在连接超时之前它不会丢弃内存并且会占用你身边或服务器上的可用连接。而且,如果我运行一个网站并发现我的服务器的性能因您的应用程序过早关闭连接而受到影响我会禁止您。

最终,您最好的解决方案是与拥有您正在掠夺的网站的任何人交谈,看看他们是否有API来告诉您文件大小是多少。由于您必须检索整个文件,因此它们的连接方可以比您的方更快地找到它。如果没有别的,请提供给他们写一些可以实现这一目标的东西。也许他们会明白,通过启用它,您将不会消耗所有带宽检索图像。