问题
I have a requirement where a zip file is sent to the ROR application after encoding it with Base64 encoding. I should decode it, save it as a zipfile and unzip it and do some operations. They are sending the zip file encoded data as a parameter called zip
through POST method. Here, is what I have done in code.
require 'rubygems'
require 'zip/zip'
require 'base64'
def get_pdf
encoded_data = Base64.decode64(params[:zip])
File.open("#{RAILS_ROOT}/zip_archive/zip_file.zip", "w") {|f| f.write encoded_data}
unzip_file("#{RAILS_ROOT}/zip_archive/zip_file.zip", "#{RAILS_ROOT}/unzipped/")
...(using @file_path, do stuff)
end
def unzip_file (file, destination)
destination = File.join(destination, File.basename(file, ".zip"))
Zip::ZipFile.open(file) { |zip_file|
zip_file.each { |f|
f_path=File.join(destination, f.name)
FileUtils.mkdir_p(File.dirname(f_path))
zip_file.extract(f, f_path) unless File.exist?(f_path)
}
}
@file_path = destination
end
But, I am not able to save the zip file correctly. The file after saving is giving error on the unzipping part.
Zip::ZipError (Zip end of central directory signature not found):
rubyzip (0.9.4) lib/zip/zip.rb:1287:in `get_e_o_c_d'
rubyzip (0.9.4) lib/zip/zip.rb:1235:in `read_e_o_c_d'
rubyzip (0.9.4) lib/zip/zip.rb:1260:in `read_from_stream'
rubyzip (0.9.4) lib/zip/zip.rb:1392:in `initialize'
rubyzip (0.9.4) lib/zip/zip.rb:1392:in `open'
rubyzip (0.9.4) lib/zip/zip.rb:1392:in `initialize'
rubyzip (0.9.4) lib/zip/zip.rb:1410:in `new'
rubyzip (0.9.4) lib/zip/zip.rb:1410:in `open'
app/controllers/pdf_controller.rb:37:in `unzip_file'
app/controllers/pdf_controller.rb:13:in `get_pdf'
When I tried to open the file outside the app also, the file was not getting opened saying
[/home/prince/Desktop/test_project/zip_archive/zip_file.zip]
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
zipinfo: cannot find zipfile directory in one of /home/prince/Desktop/test_project/zip_archive/zip_file.zip or
/home/prince/Desktop/test_project/zip_archive/zip_file.zip.zip, and cannot find /home/prince/Desktop/test_project/zip_archive/zip_file.zip.ZIP, period.
I tried saving the file with File.open("..", "wb")
to write the contents in the binary mode, but then also the same error occurs. Should I do anything to the params[:zip]
before decoding it?
回答1:
Works like a charm. The File#open
block should properly write and close the file, you're probably just having the wrong path in there somewhere. If the File.exists?
and the decode64 went through, you should be good.
ruby-1.9.2-p0 > zip = "UEsDBAoAAAAAAKphcT4AAAAAAAAAAAAAAAAFABwAZW1wdHlVVAkAA8/sgU3P\n7IFNdXgLAAEE9QEAAAQUAAAAUEsBAh4DCgAAAAAAqmFxPgAAAAAAAAAAAAAA\nAAUAGAAAAAAAAAAAAKSBAAAAAGVtcHR5VVQFAAPP7IFNdXgLAAEE9QEAAAQU\nAAAAUEsFBgAAAAABAAEASwAAAD8AAAAAAA==\n"
ruby-1.9.2-p0 > File.open('test2.zip', 'wb') {|f| f.write(Base64.decode64(zip))}
=> 160
ruby-1.9.2-p0 > Zip::ZipFile.open('test2.zip') {|z| z.each {|f| puts f.name}}
empty
=> [empty]
来源:https://stackoverflow.com/questions/5337449/base64-encoded-string-to-fileruby-on-rails