2011-02-04 11 views
6

Şu anda görüntü dosyalarını bir zip dosyasından (örneğin, bir diske kaydetmeden) doğrudan bir modele iliştirmeye çalışıyorum. Böyle bir ZipEntry bir Tempfile veya başka bir yönteme veya onunla ne yapacağını bilen nesneye geçirilmek üzere bellekte depolanabilen bir dosyaya dönüştürmenin daha açık bir yolu olmalıdır.Geçici bir File nesnesini (diske yazmadan doğru içerik türünde) doğrudan ZipEntry'den (RubyZip, Paperclip, Rails 3) nasıl alabilirim?

İşte benim kod:

def extract (file = nil) 
    Zip::ZipFile.open(file) { |zip_file| 
    zip_file.each { |image| 
     photo = self.photos.build 
     # photo.image = image # this doesn't work 
     # photo.image = File.open image # also doesn't work 
     # photo.image = File.new image.filename 
     photo.save 
    } 
    } 
end 

Ama sorun photo.image modeline (ataş yoluyla) bir ek olduğunu ve ek olarak bir şey atama şey bir dosya nesnesi olmaya gerektirir. Ancak, hayatımın bir ZipEntry'i bir Dosyaya nasıl dönüştürdüğümü anlayamıyorum. Dosya açmayı veya oluşturmayı görebilmemin tek yolu, yoluna bir dize kullanmasıdır - yani dosyayı bir konuma çıkarmak zorundayım. Gerçekten, bu sadece aptalca görünüyor. Neden ZipEntry dosyasını çıktı akışına ayıklayıp oraya bir Dosyaya dönüştüremiyorum?

Nihai soru: ZipEntry'yi bir Zip dosyasından ayıklayabilir ve doğrudan bir File nesnesine dönüştürebilir (veya doğrudan Paperclip nesnesi olarak ekleyebilir miyim)? Yoksa bu sürüm son olarak silinmiş olsa bile, sabit disk üzerinde sabit diskte saklamaktan sıkıldım mı?

UPDATE Böğürtlenli alanlar sayesinde sanırım çözümüme biraz daha yakınım. İşte ekledi kod satırı, ve o bana ihtiyacım tempfile/Dosya verir:

photo.image = zip_file.get_output_stream image 

Ancak, bir image/jpeg olmadığından, geçmiş vurmayacak dosyayı kabul etmeyecektir benim Photo nesne. Aslında, dosyanın content_type kontrol edilmesi application/x-empty gösterir. Bunun nedeni, çıktı akışının dosyaya sonuna kadar bir zaman damgası ekliyor gibi görünmesidir, bu yüzden imagename.jpg20110203-20203-hukq0n gibi görünmesini sağlayabilirsiniz. Edit: Ayrıca, oluşturduğu geçici dosya herhangi bir veri içermiyor ve 0 boyutunda. Bu, bunun yanıtı gibi görünmeyebilir.

Yani, sıradaki soru: Bir görüntü/jpeg dosyası vermek için bunu nasıl alacağını bilen var mı?

GÜNCELLEME:

Bu biraz daha etrafında çalıyorum. Çıktı akışı gitmek için bir yol değil, bir girdi akışı (ki her zaman kafamı karıştıran) gibi görünüyor. ZipEntry'de get_input_stream öğesini kullanarak, dosyadaki ikili verileri alırım. Sanırım şimdi bunu bir Paperclip eklentisine (File nesnesi olarak) nasıl alacağımı bulmalıyım. ZipInputStream'i doğrudan eke zorlamayı denedim, ama bu işe yaramıyor. Kimsenin Dosya olarak çıkarılan bir ZipEntry kullanmaya çalışmadığına inanmak gerçekten zor. Bunun kötü programlama pratiği olarak kabul edilmesinin bir nedeni var mı? Bir geçici dosya için disk yazma atlamak gibi Zip arşiv yönetimi gibi bir şey mükemmel kabul ve destek olurdu gibi görünüyor.

Neyse, soru hâlâ duruyor: File nesnesinin (veya tempfile) bir giriş akışı dönüştürme yolu

var mı? Tercihen bir diske yazmak zorunda kalmadan.

cevap

1

ZipFile'da get_input_stream ve get_output_stream iletilerine bakın.

+0

deneyin. Zip_file.get_output_stream (image) kullanımı bir Dosya ile sonuçlandı. Ancak, model bu dosyayı 'application/x-empty' olarak yorumluyor ve bu da başarısız olmasına neden oluyor. Aynı zamanda dosya adı, sürüm izleme için görüntüleri veren standart zaman damgası olduğunu varsayarak, 'image_name.jpg20110203-20203-1lyjn3i' dosya adını okuma gibi görünüyor. Bir jpeg olarak okunduğundan emin olmanın bir yolunu biliyor musun? –

+1

Aslında, sadece kontrol ettim. Çıkış akışı bir Temp Dosyası olarak açılır. Bu zaman damgası, Tempfile oluşturulduğunda eklenir. Ekstre edilen Tempfile dosyasının content_type öğesini kontrol ettim ve uygulama/x-empty olarak çıktı. –

6

Bu denedik bu

Zip::ZipFile.open(params[:avatar].path) do |zipfile| 
    zipfile.each do |entry| 
    filename = entry.name 
    basename = File.basename(filename) 

    tempfile = Tempfile.new(basename) 
    tempfile.binmode 
    tempfile.write entry.get_input_stream.read 

    user = User.new 
    user.avatar = { 
     :tempfile => tempfile, 
     :filename => filename 
    } 
    user.save 

    end 
end 
+0

Bu çalışır, ancak geçici dosya oluşturmanın sözdizimi yanlıştı. Bunu farklı bir sözdizimi kullanmak için düzenledim. – siamii

+0

Bu örnekte, user.avatar öğesini bir hash değerine ayarlıyorsunuz. User.avatar bir Paperclip :: Eklenti mi? Eğer öyleyse, bir karma nasıl geçebilir? Denedim ve benim için çalışmıyor. Ataç: Ekinde farklı nesne türleri için bir dizi "io bağdaştırıcısı" vardır (StringIO ve Tempfile gibi), ancak io_adapters'a baktım ve bir hash işlemek için bir tane göremiyorum. –

İlgili konular