我在旅游博客网站上存储了几千张高分辨率JPEG照片,我希望能够编写一些Ruby代码,从图像中提取一些关键的EXIF元数据值,而不用下载每个图像文件的全部内容(它们很大,我有很多)。
我正在使用'exifr'gem来读取EXIF数据,它可以用于任何类型的IO对象,而不仅仅是本地文件。但是,Net::HTTPResponse
对象实际上不是IO对象,但如果将read_body
方法传递给块,它确实允许增量读取。然而,我读过有关这个增量读数是否真的允许你只下载文件的一部分的报告,或者它是否只是让你以块的形式读取内容以提高效率(即无论如何都要下载整个内容)。 / p>
那么,我正在努力做到这一点吗?我应该查看Net::HTTP
的替代方案,还是有一些方法可以让我获得低级TCP套接字(应该是一个IO对象)来传递给'exifr'代码来读取足够的获取EXIF数据的图像?其他解决方案?
答案 0 :(得分:2)
我生成了一张快速表格,其中列出了我的照片中存储的EXIF数据:
$ find . -type f -exec grep -a -bo Exif {} \; > /tmp/exif
$ sort /tmp/exif | uniq -c | sort -n
1 12306:Exif
1 3271386:Exif
1 8210:Exif
1 8234:Exif
1 9234:Exif
2 10258:Exif
24 449:Exif
30 24:Exif
8975 6:Exif
$
明显多数只是文件中的几个字节;少数人分散在其他地方,但最差的只有3兆字节。 (给予或接受。)
我编写了一个小测试脚本,似乎可以为单个URL执行必要的操作。 (通过在我可用的巨大二进制文件的块中查找字符串AA
来测试。)这当然不是我编写的最漂亮的程序,但它可能是解决方案的充分开端。请注意,如果Exif
文本跨越块,您将检索整个文件。那真不幸。我希望它不会经常发生。 66000
就在那里,因为JPEG AAP1块的大小限制为64千字节,而抓取更多可能比抓取更少一点。
#!/usr/bin/ruby
require 'net/http'
require 'uri'
url = URI.parse("http://....")
begin
looking = true
extra_size = 0
File.open("/tmp/output", "w") do |f|
Net::HTTP.start(url.host, url.port) do |http|
request = Net::HTTP::Get.new url.request_uri
http.request request do |resp|
resp.read_body do |chunk|
f.write chunk
if (looking)
if (chunk.match(/Exif/))
looking = false
end
elsif (extra_size < 66000)
extra_size += chunk.length
else
throw "done"
end
end
end
end
end
rescue
puts "done"
exit(0)
end