我的代码中有一个函数,该函数接受代表图像url的File
字符串,并根据该字符串创建对象,并将其附加到Tweet。这似乎有90%的时间有效,但偶尔会失败。
require 'open-uri' attachment_url = "https://s3.amazonaws.com/FirmPlay/photos/images/000/002/443/medium/applying_too_many_jobs_-_daniel.jpg?1448392757" image = File.new(open(attachment_url))
如果我运行上面的代码,它将返回TypeError: no implicit conversion of StringIO into String
。如果我改变open(attachment_url)
了open(attachment_url).read
我会得到ArgumentError: string contains null byte
。我还尝试像这样从文件中删除空字节,但这也没有区别。
image = File.new(open(attachment_url).read.gsub("\u0000", ''))
现在,如果我尝试使用其他图像(例如下面的图像)尝试原始代码,则可以正常工作。它File
按预期返回一个对象:
attachment_url = "https://s3.amazonaws.com/FirmPlay/photos/images/000/002/157/medium/mike_4.jpg"
我以为可能与原始网址中的参数有关,所以我删除了这些参数,但这没什么区别。如果我在Chrome中打开图像,则看起来效果很好。
我不确定我在这里缺少什么。我该如何解决这个问题?
谢谢!
更新资料
这是我的应用程序中的工作代码:
filename = self.attachment_url.split(/[\/]/)[-1].split('?')[0] stream = open(self.attachment_url) image = File.open(filename, 'w+b') do |file| stream.respond_to?(:read) ? IO.copy_stream(stream, file) : file.write(stream) open(file) end
Jordan的答案有效,除了调用File.new
返回一个空File
对象,而File.open
返回一个File
包含来自的图像数据的对象stream
。
您得到的原因TypeError: no implicit conversion of StringIO into String
是open
有时返回一个String对象,有时返回一个StringIO对象,这是不幸的并且令人困惑。它的作用取决于文件的大小。请参阅此答案以获取更多信息:open-uri从以iso-8859编码的网页返回ASCII-8BIT(尽管我不建议使用其中提到的sure-encoding gem,因为自2010年以来就没有对其进行更新,而Ruby已经此后与编码相关的重大变化。)
得到的原因ArgumentError: string contains null byte
是您试图将图像数据作为第一个参数传递给File.new
:
image = File.new(open(attachment_url))
的第一个参数File.new
应该是文件名,并且在大多数系统上,文件名中不允许使用空字节。尝试以下方法:
image_data = open(attachment_url) filename = 'some-filename.jpg' File.new(filename, 'wb') do |file| if image_data.respond_to?(:read) IO.copy_stream(image_data, file) else file.write(image_data) end end
上面的代码打开了文件(如果文件不存在,则创建它;b
in 'wb'
告诉Ruby您将要写入二进制数据),然后image_data
使用IO.copy_stream
它是StreamIO对象或File#write
其他对象,使用该文件向其中写入数据,然后关闭文件再次。