简体   繁体   中英

ruby reading files from S3 with open-URI

I'm having some problems reading a file from S3. I want to be able to load the ID3 tags remotely, but using open-URI doesn't work, it gives me the following error:

ruby-1.8.7-p302 > c=TagLib2::File.new(open(URI.parse("http://recordtemple.com.s3.amazonaws.com/music/745/original/The%20Stranger.mp3?1292096514")))
TypeError: can't convert Tempfile into String
    from (irb):8:in `initialize'
    from (irb):8:in `new'
    from (irb):8

However, if i download the same file and put it on my desktop (ie no need for open-URI), it works just fine.

c=TagLib2::File.new("/Users/momofwombie/Desktop/blah.mp3")

is there something else I should be doing to read a remote file?

UPDATE: I just found this link, which may explain a little bit, but surely there must be some way to do this...

Read header data from files on remote server

Might want to check out AWS::S3 , a Ruby Library for Amazon's Simple Storage Service

Do an AWS::S3:S3Object.find for the file and then an use about to retrieve the metadata

This solution assumes you have the AWS credentials and permission to access the S3 bucket that contains the files in question.

This solution isn't going to work much longer. Paperclip > 3.0.0 has removed to_file. I'm using S3 & Heroku. What I ended up doing was copying the file to a temporary location and parsing it from there. Here is my code:

dest = Tempfile.new(upload.spreadsheet_file_name)
dest.binmode
upload.spreadsheet.copy_to_local_file(:default_style, dest.path)
file_loc = dest.path 

...

CSV.foreach(file_loc, :headers => true, :skip_blanks => true) do |row|}

TagLib2::File.new doesn't take a file handle, which is what you are passing to it when you use open without a read .

Add on read and you'll get the contents of the URL, but TagLib2::File doesn't know what to do with that either, so you are forced to read the contents of the URL, and save it.

I also noticed you are unnecessarily complicating your use of OpenURI. You don't have to parse the URL using URI before passing it to open . Just pass the URL string.

require 'open-uri'

fname = File.basename($0) << '.' << $$.to_s
File.open(fname, 'wb') do |fo|
  fo.print open("http://recordtemple.com.s3.amazonaws.com/music/745/original/The%20Stranger.mp3?1292096514").read
end

c = TagLib2::File.new(fname)

# do more processing...

File.delete(fname)

I don't have TagLib2 installed but I ran the rest of the code and the mp3 file downloaded to my disk and is playable. The File.delete would clean up afterwards, which should put you in the state you want to be in.

This seems to work instead of open-URI:

Mp3Info.open(mp3.to_file.path) do |mp3info|
  puts mp3info.tag.artist
end

Paperclip has a to_file method that downloads the file from S3.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM