open-uri を使用してリモート画像をダウンロードしてから、imagesize gem を使用して寸法を取得しています。問題は、一握り以上の画像を処理する必要がある場合、これが非常に遅くなることです。
さまざまな画像形式のサイズを知るのに十分な情報をダウンロードするにはどうすればよいですか?
これを最適化する方法は他にありますか?
raw ソケットを使用する (必要最小限の 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
たとえば、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
通常の HTTPd リクエストでダウンロードするバイト数を指定する方法を知りません。それはオール・オア・ナッシングの状況です。
一部のファイル タイプではファイルのセクションを許可しますが、それを有効にするにはサーバーを制御する必要があります。
このレベルでプレイしてから長い時間が経ちましたが、理論的には、Net::HTTP または Open-URI でブロックを使用し、画像サイズのブロックに到達するための適切な数を受け取るまでバイトをカウントできます。 、接続を閉じます。あなたの TCP スタックは、特にあなたがそれを頻繁に行っていた場合、おそらくあまり満足していないでしょう。私の記憶が正しければ、接続がタイムアウトするまでメモリを破棄せず、あなたの側またはサーバー側で利用可能な接続を使い果たします。また、私がサイトを運営していて、あなたのアプリが時期尚早に接続を閉じたため、サーバーのパフォーマンスが損なわれていることがわかった場合は、あなたを追放します。
最終的に、最善の解決策は、あなたが略奪しているサイトの所有者と話し、ファイル サイズを教えてくれる API があるかどうかを確認することです。ファイル全体を取得する必要があるため、接続の彼らの側はあなたの側よりもはるかに速くそれを見つけることができます. 他に何もないとしても、それを達成できる何かを書くことを申し出てください。おそらく彼らは、それを有効にすることで、画像を取得するためにすべての帯域幅を消費しないことを理解するでしょう.