Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Ruby从远程图像高效读取EXIF元数据_Ruby_Http_Exif - Fatal编程技术网

使用Ruby从远程图像高效读取EXIF元数据

使用Ruby从远程图像高效读取EXIF元数据,ruby,http,exif,Ruby,Http,Exif,我有几千张高分辨率JPEG照片存储在一个旅游博客网站上,我希望编写一些Ruby代码,从图像中提取一些关键的EXIF元数据值,而无需下载每个图像文件的全部内容(它们很大,我有很多) 我正在使用“exifr”gem读取EXIF数据,它设计用于任何类型的IO对象,而不仅仅是本地文件。但是,Net::HTTPResponse对象实际上并不是一个IO对象,尽管如果您将read\u body方法传递给一个块,它确实允许增量读取。然而,我读过一些相互矛盾的报告,关于这种增量读取是否真的允许您只下载文件的一部分

我有几千张高分辨率JPEG照片存储在一个旅游博客网站上,我希望编写一些Ruby代码,从图像中提取一些关键的EXIF元数据值,而无需下载每个图像文件的全部内容(它们很大,我有很多)

我正在使用“exifr”gem读取EXIF数据,它设计用于任何类型的IO对象,而不仅仅是本地文件。但是,
Net::HTTPResponse
对象实际上并不是一个IO对象,尽管如果您将
read\u body
方法传递给一个块,它确实允许增量读取。然而,我读过一些相互矛盾的报告,关于这种增量读取是否真的允许您只下载文件的一部分,或者它是否只允许您为提高效率而分块读取内容(即,无论如何都要下载整个内容)


那么,我想做的是可能的吗?我应该寻找
Net::HTTP
的替代方案,还是有什么方法可以让我使用低级TCP套接字(应该是一个IO对象)来传递给“exifr”代码,以读取刚好足够的图像来获取EXIF数据?其他解决方案?

我生成了一个快速表格,列出了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
#/usr/bin/ruby
需要“net/http”
需要“uri”
url=URI.parse(“http://....")
开始
外观=真实
额外大小=0
打开(“/tmp/output”,“w”)do|f|
Net::HTTP.start(url.host,url.port)do | HTTP|
request=Net::HTTP::Get.new url.request\u uri
http.request do | resp|
分别为读体做块|
f、 写块
如果(看)
if(chunk.match(/Exif/))
看=假
结束
elsif(额外尺寸<66000)
额外大小+=chunk.length
其他的
抛出“完成”
结束
结束
结束
结束
结束
营救
“完成”
出口(0)
结束

我快速浏览了一下,不知道EXIF数据包是否位于文件中的“可靠”位置?给定的摄像头可能是可预测的,但我认为您不能可靠地期望EXIF数据位于文件的末尾或开头。。。如果你能找出文件中EXIF数据的字节偏移量,这会很有帮助,你必须看看它是否足够类似于一些启发式方法……这太棒了。我们如何像另一个需要文件的Exif gem一样使用它来输入程序?我是否有权访问
块中的完整“部分文件”或其他内容?我能把它当作文件吗?