I have a function in my code that takes a string representing the url of an image and creates a File
object from that string, to be attached to a Tweet. This seems to work about 90% of the time, but occasionally fails.
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))
If I run the above code it returns TypeError: no implicit conversion of StringIO into String
. If I change open(attachment_url)
to open(attachment_url).read
I get ArgumentError: string contains null byte
. I also tried stripping out the null bytes from the file like so, but that also made no difference.
image = File.new(open(attachment_url).read.gsub("\u0000", ''))
Now if I try the original code with a different image, such as the one below, it works fine. It returns a File
object as expected:
attachment_url = "https://s3.amazonaws.com/FirmPlay/photos/images/000/002/157/medium/mike_4.jpg"
I thought maybe it had something to do with the params in the original url, so I stripped those out, but it made no difference. If I open the images in Chrome they appear to be fine.
I'm not sure what I'm missing here. How can I resolve this issue?
Thanks!
Update
Here is the working code I have in my app:
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's answer works except that calling File.new
returns an empty File
object, whereas File.open
returns a File
object containing the image data from stream
.