2009-11-11 3 views
1

Я передаю местоположение динамического zip-файла в def из базы данных. Я хочу разархивировать файл во временное местоположение, извлечь файл отчета xml внутри, применить таблицу стилей xslt, скопировать ее как rhtml в каталог представления для рендеринга и удалить извлеченный temp файл xml. Функциональность работает нормально (файл rhtml перезаписывается каждый раз и визуализуется), за исключением того, что он извлекает из одного и того же родительского почтового индекса для каждого выполнения, и извлеченный XML не может быть удален, что заставляет меня думать, что первое выполнение не закрывает родительский zip (освобождение его ручки). Следовательно, последующие исполнения извлекают xml из первого выполненного zip. Я пробовал «Zip :: ZipFile.close», «zipFile = Zip :: ZipFile.open (fileLocation); zipFile.close», «File.close (fileLocation)» и другие перестановки. Любая помощь будет оценена по достоинству.Как закрыть ZipFile

ответ

0

Можете ли вы передать блок Zip :: ZipFile.open? Это закроет его, когда блок выходит:

Zip::ZipFile.open(file_name) do |zip_file| 
    zip_file.extract('report.xml', '/tmp') 
end 

# zip file is closed at this point 
# apply_xslt 
# copy rhtml to app/views/... 
# etc 

== EDIT ==

на основе ваших комментариев, вот рабочий пример:

require 'rubygems' 
require 'zip/zip' 
require 'fileutils' 

zip_file_name = 'test.zip' 
out_dir = 'tmp_for_zip' 
FileUtils.mkdir_p out_dir 

Zip::ZipFile.open(zip_file_name) do |zip_file| 
    report_name = File.basename(zip_file.name).gsub('zip', 'xml') 
    out = File.join(out_dir, report_name) 
    zip_file.extract(report_name, out) unless File.exists?(out) 
    puts "extracted #{report_name} to #{out}" 
end 

Кроме того, я не знаю, если вы используете unix, но вы можете использовать lsof (список открытых файлов), чтобы выяснить, действительно ли файл открыт:

lsof | grep your_file_name 
+0

Я не знаю названия o f 'report.xml'. Я делал это динамически с помощью цикла: Zip :: ZipFile.open (file.to_s) {| zip_file | zip_file.each {| f | @Base = File.basename (f.name) @f_path = File.join (TEMPDIR, @ основание) \t \t \t FileUtils.mkdir_p (File.dirname (@f_path)) zip_file.extract (е, @f_path) если File.exist? (@ f_path) zip_file.close } \t \t \t } название 'report.xml' имеет такое же имя, как корень почтового индекса ("blah_report.xml" в «blah_report. zip "), поэтому я предполагаю, что могу разобрать его, но это похоже на боль (и не слишком эффективный - или элегантный) –

+0

Есть ли способ сделать« zip_file.extract (во-первых, '/ tmp') "? На zip будет только 1 отчет. –

+0

К сожалению, ваш код дает тот же результат, что и мой оригинал. У меня все еще есть 2 проблемы. Как только xml извлекается, я использую его для создания объекта XML Document, применяю таблицу стилей XSLT и копирую результат в «views /.../ sampleReport.rhtml» для рендеринга. Исходный xml не может быть удален (через код или вручную), пока сервер не будет отключен, чтобы выпустить файл. (Возможно ли, что объект Doc все еще держится за него, а не от zip-родителя). Кроме того, рендеринг нового rhtml всегда показывает результат первого выполнения, даже если я проверил, что rhtml изменился. Может ли это быть проблемой кэширования? –

Смежные вопросы