8000 Undefined method 'path' · Issue #119 · rubyzip/rubyzip · GitHub
[go: up one dir, main page]

Skip to content

Undefined method 'path' #119

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mperham opened this issue Jan 3, 2014 · 16 comments
Closed

Undefined method 'path' #119

mperham opened this issue Jan 3, 2014 · 16 comments

Comments

@mperham
Copy link
Contributor
mperham commented Jan 3, 2014

I'm just doing this where det.content is a String of binary data.

Zip::File.open_buffer(det.content) do |zipfile|
end
     NoMethodError:
       undefined method `path' for #<StringIO:0x007fe9036804e0>
     # ./.bundle/ruby/2.0.0/gems/rubyzip-1.1.0/lib/zip/entry.rb:180:in `read_c_dir_entry'
     # ./.bundle/ruby/2.0.0/gems/rubyzip-1.1.0/lib/zip/central_directory.rb:124:in `block in read_central_directory_entries'
     # ./.bundle/ruby/2.0.0/gems/rubyzip-1.1.0/lib/zip/central_directory.rb:123:in `times'
     # ./.bundle/ruby/2.0.0/gems/rubyzip-1.1.0/lib/zip/central_directory.rb:123:in `read_central_directory_entries'
     # ./.bundle/ruby/2.0.0/gems/rubyzip-1.1.0/lib/zip/central_directory.rb:135:in `read_from_stream'
     # ./.bundle/ruby/2.0.0/gems/rubyzip-1.1.0/lib/zip/file.rb:128:in `open_buffer'
@simonoff
Copy link
Member
simonoff commented Jan 6, 2014

@mperham Sorry I'm on vacation now. Can you check my fix and tell me what all works fine. Thank you for the issue!

@mperham
Copy link
Contributor Author
mperham commented Jan 6, 2014

Now I get this:

     Failure/Error: processor.perform(det.id)
     Errno::ENOENT:
       No such file or directory - 
     # ./.bundle/ruby/2.0.0/bundler/gems/rubyzip-18506c6345d3/lib/zip/input_stream.rb:117:in `initialize'
     # ./.bundle/ruby/2.0.0/bundler/gems/rubyzip-18506c6345d3/lib/zip/input_stream.rb:117:in `open'
     # ./.bundle/ruby/2.0.0/bundler/gems/rubyzip-18506c6345d3/lib/zip/input_stream.rb:117:in `get_io'
     # ./.bundle/ruby/2.0.0/bundler/gems/rubyzip-18506c6345d3/lib/zip/input_stream.rb:52:in `initialize'
     # ./.bundle/ruby/2.0.0/bundler/gems/rubyzip-18506c6345d3/lib/zip/entry.rb:494:in `new'
     # ./.bundle/ruby/2.0.0/bundler/gems/rubyzip-18506c6345d3/lib/zip/entry.rb:494:in `get_input_stream'
     # ./.bundle/ruby/2.0.0/bundler/gems/rubyzip-18506c6345d3/lib/zip/file.rb:225:in `get_input_stream'
     # ./.bundle/ruby/2.0.0/bundler/gems/rubyzip-18506c6345d3/lib/zip/file.rb:257:in `read'

Could you write a test which reproduces my problem? That'll get us to a fix quicker. Here's the actual code I'm using, modified to work with the rubyzip project so you can use it for a test:

fname = "./README.md"
zname = "README.zip"
Zip::File.open(zname, Zip::File::CREATE) do |zipfile|
  zipfile.get_output_stream(File.basename(fname)) { |f| f.puts File.read(fname) }
end

data = nil
Zip::File.open_buffer(File.read(zname)) do |zipfile|
  zipfile.each do |entry|
    next unless entry.name =~ /README.md/
    data = zipfile.read(entry)
  end
end
assert data
assert data =~ /Simonov/

I'm using a buffer, not reading from a file, because the zip data is actually coming from our database.

mperham added a commit to mperham/rubyzip that referenced this issue Jan 6, 2014
simonoff added a commit that referenced this issue Jan 7, 2014
simonoff added a commit that referenced this issue Jan 19, 2014
@simonoff
Copy link
Member

@mperham fixed. Can you test it on your application?

@mperham
Copy link
Contributor Author
mperham commented Jan 20, 2014

I don't have the bandwidth anymore but if the test passes I'll trust that things are better now.

@simonoff
Copy link
Member

@mperham ok. Thank you for your help.

@timmi-on-rails
Copy link

mperham , did you manage to read the zipfile from the database? I am not able todo it properly. The only solution I found is this http://stackoverflow.com/questions/13730720/how-to-iterate-through-an-in-memory-zip-file-in-ruby where I have to change the StringIO class. In case you got it to work, can you please tell me how? Your code above from the test does not work, it fails with:

 Zip::ZipFile.open_buffer expects an argument of class String or IO. Found: String 
, which makes no sense to me.

@timmi-on-rails
Copy link

Sorry, for some reason I still had version 1.0.0 installed

@simonoff
Copy link
Member

@timmi-on-rails so you updated to fixed version? or not?

@timmi-on-rails
Copy link

I am using axlsx, that was the reason for the old version of rubyzip used... (now I use the zip-zip gem for compatibility, but it doesn't work with axlsx, but nvm, I guess I can somehow use the old and new gem at the same time?!)

Having version 1.1.2 now
Reading from memory doesnt work like described above, so what works is:
reading from a file with:

Zip::File.open(fname) do |zipfile| end

what doesnt work is

Zip::File.open_buffer(File.read(fname)) ... 
with the same file, I get:
Zip end of central directory signature not found

If I actually put some in memory data from my database

Zip::File.open_buffer(@project.probe_data) ... 

I get:

undefined method `bytesize' for nil:NilClass
, somewhere in the entry.rb ...(read_local_entry)

Then I tried using InputStream.open_buffer , but I get different problems there... :-(

I just want to read a zipfile that I have as binary string stored in a variable.

@timmi-on-rails
Copy link

In the old API this works for me:

Zip::InputStream.open_buffer(StringIO.new(@project.probe_data)) do |io|
   while entry = io.get_next_entry
      logger.debug entry.name
   end
end

with this patch:

class StringIO
    def path
    end
end

However in the new API this doesnt work.

@timmi-on-rails
Copy link

I just found issue #105 and wanted to add, that I am dealing with xlsx files aswell, so it seems the problem is related to #105 rather ...

< 8000 !-- -->

@simonoff
Copy link
Member

In new version your code must working too!

Zip::InputStream.open_buffer(StringIO.new(@project.probe_data)) do |io|
   while entry = io.get_next_entry
      logger.debug entry.name
   end
end

There is no need to have path in StringIO

@timmi-on-rails
Copy link

Well that code returns zero entries in the new version and a deprecated warning. I just found out that it works in the new version, if I use Zip::InputStream.open instead of Zip::InputStream.open_buffer

The the undefined method "bytesize" seems to be a whole other issue that only happens for "xlsx" files. Actually if I create a zip with not just plain files, but subfolders, the issue happens. But I am not sure about the exact circumstances.

Edit:
Ok its not the subdir thing, but somehow the content of the files in the zip, the encoding maybe. Happens for example if I put a xlsx file Inside the archive..., then I get the Nil Class undefined method bytesize
Plus It seems to be just a problem when reading from buffer... When I run through the file directly with Zip::InputStream.open(file_name) then everything is okay ... but StringIO.new(File.read(file_name)) ensures this strange behavior

@timmi-on-rails
Copy link

File: entry.rb in method: read_local_entry, the line

  static_sized_fields_buf = io.read(::Zip::LOCAL_ENTRY_STATIC_HEADER_LENGTH) 

evaluates as Nil Class, therefore in line 224

unless static_sized_fields_buf.bytesize == ::Zip::LOCAL_ENTRY_STATIC_HEADER_LENGTH 

complains the missing bytesize method

I don't have a fix yet, because I dont know the whole thing very well :(

@changemewtf
Copy link
Contributor
8000

I am running into the same problem with this zip file, containing only two files, solution.rb and README.md.

This:

Zip::File.open_buffer(File.open('thing.zip'))

And this:

Zip::File.open_buffer(File.read('thing.zip'))

Both result in this:

NoMethodError: undefined method `bytesize' for nil:NilClass
from /Users/mcantor/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/rubyzip-1.1.6/lib/zip/entry.rb:341:in `check_c_dir_entry_static_header_length'

I noticed in zip/file.rb on line 426, the way it opens files when you use Zip::File.open with a filename is like so:

        ::File.open(name, 'rb') do |f|

I tried this:

Zip::File.open_buffer(File.open('thing.zip', 'rb'))

And got a different error:

ArgumentError: wrong number of arguments (0 for 1..2)
from /Users/mcantor/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/rubyzip-1.1.6/lib/zip/output_stream.rb:32:in `reopen'

It seems the interface of IO#reopen() may have changed or something, because it looks like you're supposed to specify either another IO object, or a path and a mode.

@aalvarado
Copy link

Please check if setting the encoding in your StringIO object solves the issue, it did for me on a related problem I had:

#177 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants
0