On-the-fly, yüksek hızda PHP + Apache ile oluşturuluyor ZIP dosyaları?

5 Cevap php

Bazı alıntı famous words:

"Programcılar ... sık sık iş karmaşıklık ve marifet yolunda, anlaşılabilir, ama felaket eğim sığınmak. Bir program daha büyük bir şey tasarlamak yasak, onların mesleki beceri meydan için yeterli o program karmaşık yaparak yanıt verir. "

Iş yerinde bazı sıradan problem çözerken ben çözmek için nasıl emin değilim bu fikri ile geldi. Ben bu uygulama olmayacak biliyorum, ama ben iyi çözümdür ne kadar çok merak ediyorum. :)


JPG dosyaları ve birkaç garip SWF dosyaları ile bu büyük bir koleksiyona sahip varsayalım. "Büyük" dedim, "Bir kaç bin" demek ile. Her JPG dosyası 200KB etrafında ve SWF birkaç MB boyutunda kadar olabilir. Her gün birkaç yeni JPG dosyaları var. Tüm malzeme toplam boyutu böylece yaklaşık 1 GB, ve yavaş yavaş ama istikrarlı bir şekilde artmaktadır. Dosyalar ÇOK nadiren değiştirilebilir veya silinir.

Kullanıcıların web sayfasında tek tek dosyaların her görebilirsiniz. Ancak onları bir kez onları bir sürü indirmek için izin isteği de var. Dosyaları kullanıcı tarafından koleksiyon filtre onlara (tarih, kategori, vb) bağlı bazı meta var.

Nihai uygulama ardından kullanıcı bazı filtre ölçütlerini belirlemek ve daha sonra tek bir ZIP dosyası olarak gelen dosyaları indirmek için izin olacaktır.

Kriterleri miktarı yeterince büyük olduğundan, tüm olası ZIP dosyaları pre-üretemez ve on-the-fly bunu yapmak gerekir. Başka bir sorun indirme oldukça büyük olabilir ve yavaş bağlantıları olan kullanıcılar için onu bir saat veya daha fazla sürer oldukça muhtemel olmasıdır. "Özgeçmiş" için destek dolayısıyla bir-olması gerekir.

Parlak tarafında ancak ZIP şey sıkıştırmak gerekmez - dosya zaten çoğunlukla JPEG vardır. Böylece bütün süreç daha yoğun CPU, basit bir dosya indirme daha olmamalıdır.

Problemler sonra tespit ettiklerini, böylece şunlardır:

  • PHP için yürütme zaman aşımı vardır. Bu komut dosyası kendisi tarafından değiştirilebilir iken, bunu tamamen kaldırarak hiçbir sorun olacak?
  • Özgeçmiş seçeneği ile farklı HTTP istekleri için değişen filtre sonuçlarının olasılığı vardır. Koleksiyonu yalnızca büyük oluyor gibi bu, kronolojik sonuçları sıralayarak hafifletilebilir olabilir. Başlangıçta oluşturulan ve senaryo o daha genç dosyalar dikkate olmaz ne zaman isteği URL bundan sonra da bir tarih yer alacak. Bu yeterli olacak mı?
  • PHP ile dosya büyük miktarda veri geçen başlı başına bir performans hit olmayacak?

How would you implement this? Is PHP up to the task at all?


Added:

Artık iki kişi geçici bir klasöre ve orada her zamanki dosyaları olarak onları hizmet talep ZIP dosyalarını depolamak için önerdi. Bu gerçekten bariz bir çözüm olsa da, bu olanaksız hale birkaç pratik hususlar var.

ZIP dosyaları genellikle megabayt birkaç onlarca megabayt hundreads değişen, oldukça büyük olacaktır. Bu ZIP dosya boyutu gigabyte üzerinde olacak, yani, aynı zamanda "her şeyi" istemek için bir kullanıcı için tamamen normaldir. Ayrıca orada birçok olası filtre kombinasyonları ve çoğu kullanıcı tarafından seçilen olması muhtemeldir.

Sonuç olarak, ZIP dosyaları (nedeniyle veri ve disk hızı hacmi için) oluşturmak için, ve tüm koleksiyonu, defalarca içerecek oldukça yavaş olacaktır. Bu çözüm bazı mega pahalı SCSI RAID dizi olmadan işe nasıl görmüyorum.

5 Cevap

This may be what you need: http://pablotron.org/software/zipstream-php/

Bu lib diske takas olmadan dinamik akış zip dosyası oluşturmanızı sağlar.

Onları yüklemeleri devam edebilmek istiyorsanız, oluşturulan zip dosyasını saklamak zorunda gidiyoruz.

Temelde zip dosyası oluşturmak ve (belki arama filtrelerin karma) bir tekrarlanabilir dosya adı ile bir / tmp dizininde fırlat. Sonra kullanıcı için kullanıcı ve yankı file_get_contents için doğru başlıkları gönderin.

Eğer değer $ _SERVER ['HTTP_RANGE'] kontrol etmek gerekir sürdürme desteklemek için, senin bu gibi bir şey çalıştırmak gerekir ki çözümlü kez biçimi ayrıntılı here ve var.

$size = filesize($zip_file);

if(isset($_SERVER['HTTP_RANGE'])) {
    //parse http_range
    $range = explode( '-', $seek_range);
    $new_length = $range[1] - $range[0]
    header("HTTP/1.1 206 Partial Content");
    header("Content-Length: $new_length");
    header("Content-Range: bytes {$range[0]}-$range[1]");
    echo file_get_contents($zip_file, FILE_BINARY, null, $range[0], $new_length);
} else {
    header("Content-Range: bytes 0-$size");
    header("Content-Length: ".$size);
    echo file_get_contents($zip_file);
}

Bu çok kabataslak kod, muhtemelen HTTP_RANGE değişkeni biraz üzere başlıkları ve içeriği ile oynamak gerekir. Sadece fseek doğru yere isteyen ve eğer fopen ve fwrite yerine file_get içeriğini kullanabilirsiniz.

Şimdi sorularınıza

  • PHP için yürütme zaman aşımı vardır. Bu komut dosyası kendisi tarafından değiştirilebilir iken, bunu tamamen kaldırarak hiçbir sorun olacak?

Eğer isterseniz, bunu kaldırabilirsiniz şey giderse bu sonsuz döngü bir yerde oturum ve hata gerektiğini ancak armut biçimli ve kod bir sonsuz döngü içinde takılıp ilginç problemlere yol açabilir ve size kadar oldukça öfkeli bir fark yoktur Onların sunucu sabit disk alanı bitti neden sys-admin merak ;)

  • Özgeçmiş seçeneği ile farklı HTTP istekleri için değişen filtre sonuçlarının olasılığı vardır. Koleksiyonu yalnızca büyük oluyor gibi bu, kronolojik sonuçları sıralayarak hafifletilebilir olabilir. Başlangıçta oluşturulan ve senaryo o daha genç dosyalar dikkate olmaz ne zaman isteği URL bundan sonra da bir tarih yer alacak. Bu yeterli olacak mı?

Sabit diske dosyayı önbelleğe, sen alışkanlık bu sorun var demektir.

  • PHP ile dosya büyük miktarda veri geçen başlı başına bir performans hit olmayacak?

Evet webserver bir düzenli indirmek kadar hızlı olmayacak. Ama çok düşük olmamalıdır.

i have a download page, and made a zip class that is very similar to your ideas. my downloads are very big files, that can't be zipped properly with the zip classes out there.

and i had similar ideas as you. the approach to give up the compression is very good, with that you not even need fewer cpu resources, you save memory because you don't have to touch the input files and can pass it throught, you can also calculate everything like the zip headers and the end filesize very easy, and you can jump to every position and generate from this point to realize resume.

I go even further, i generate one checksum from all the input file crc's, and use it as an e-tag for the generated file to support caching, and as part of the filename. If you have already download the generated zip file the browser gets it from the local cache instead of the server. You can also adjust the download rate (for example 300KB/s). One can make zip comments. You can choose which files can be added and what not (for example thumbs.db).

But theres one problem that you can't overcome with the zip format completely. Thats the generation of the crc values. Even if you use hash-file to overcome the memory problem, or use hash-update to incrementally generate the crc, it will use to much cpu resources. Not much for one person, but not recommend for professional use. I solved this with an extra crc value table that i generate with an extra script. I add this crc values per parameter to the zip class. With this, the class is ultra fast. Like a regular download script, as you mentioned.

Benim zip sınıf devam eden bir çalışmadır, burada ona bir göz atabilirsiniz: http://www.ranma.tv/zip-class.txt

Ben bu konuda birisi yardımcı olabilir umuyoruz :)

But i will discontinue this approach, i will reprogram my class to a tar class. With tar i don't need to generate crc values from the files, tar only need some checksums for the headers, thats all. And i don't need an extra mysql table any more. I think it makes the class easier to use, if you don't have to create an extra crc table for it. It's not so hard, because tars file structure is easier as the zip structure.

PHP için yürütme zaman aşımı vardır. Bu komut dosyası kendisi tarafından değiştirilebilir iken, bunu tamamen kaldırarak hiçbir sorun olacak?

If your script is safe and it closes on user abort, then you can remove it completely. But it would be safer, if you just renew the timeout on every file that you pass throught :)

Özgeçmiş seçeneği ile farklı HTTP istekleri için değişen filtre sonuçlarının olasılığı vardır. Koleksiyonu yalnızca büyük oluyor gibi bu, kronolojik sonuçları sıralayarak hafifletilebilir olabilir. Başlangıçta oluşturulan ve senaryo o daha genç dosyalar dikkate olmaz ne zaman isteği URL bundan sonra da bir tarih yer alacak. Bu yeterli olacak mı?

Yes that would work. I had generated a checksum from the input file crc's. I used this as an e-tag and as part of the zip filename. If something changed, the user can't resume the generated zip, because the e-tag and filename changed together with the content.

PHP ile dosya büyük miktarda veri geçen başlı başına bir performans hit olmayacak?

No, if you only pass throught it will not use much more then a regular download. Maybe 0.01% i don't know, its not much :) I assume because php don't do much with the data :)

Kullan mesela PhpConcept Library Zip kitaplığı.

Yerden Devam doğrudan zipfiles erişilebilir yapmayın vaka hariç sunucunuza tarafından desteklenmesi gerekir. Eğer arabulucu olarak bir php komut dosyası varsa sürdürme desteklemek için doğru başlıkları gönderme dikkat.

Dosyaları oluşturma komut şimdiye kadar sadece kullanıcılar aynı anda binlerce dosya seçemezsiniz emin zaman aşımı olmamalı. Ve "eski zipfiles" kaldırmak ve bazı kötü niyetli kullanıcı birçok farklı filecollections talep ederek Diskspace kadar kullanabilirsiniz olmadığını dışarı izlemek için yerinde bir şeyler tutun.

Yerine PHP tüm içerik yüklenmesi ve daha sonra gönderme, parçalar halinde bölünmüş tarayıcınıza anında sıkıştırılmış dosya göndermek, hangi ZipStream or PHPZip kullanabilirsiniz zip dosyası.

Hem kütüphaneleri kod güzel ve kullanışlı parçalarıdır. Birkaç ayrıntıları: