Güvenilmez İndirme: PHP Dosya Komut Porsiyon?

3 Cevap php

Bu yazı ServerFault ilgili bir soru (http://serverfault.com/questions/131156/user-receiving-partial-downloads) olarak başladı ama bizim php script suçlu olduğunu belirledi. Ben de gerçek bir mesele olduğuna inanıyorum ne hakkında burada güncel bir soru çıkartıyorum.

Ben izinleri doğrulamak ve daha sonra indirmek için benim web kullanıcıları için bir dosya kadar hizmet bir php komut dosyası kullanıyorum. Çoğu zaman, bu çalışır, ancak son zamanlarda bir kullanıcı büyük siteleri ile ilgili sorunlar görülmeye olmuştur. O sadece boyutu> 100MB dosyalar için ~ indirmelerin% 80 oluyor. Ayrıca, bu komut tüm indirme bir dosya boyutu bildirmek için başarısız. Ayrıca, testler (dosya boyutu bildirilen hangi noktada) doğrudan bir bağlantı verilirse aynı kullanıcı güvenilir başarısız dosyaların her indirilmesine OLABİLİR ortaya koymuştur.

Burada dosyayı hizmet için kullandığınız kod ilgili pasajı var:

header("Content-type:$contenttype");
$len = filesize($filename);
header("Content-Length: $len");
header("Content-Disposition: attachment; filename=".$title.".".$ext);
readfile($filename);

Buraya gelmeden önce o $ ContentType'ı, $ dosya, $ başlık, ve $ ext Not doğru ayarlanmış. Bu üçlü-kontrol edilmiştir. Bunların hiçbiri sorun vardır. Ayrıca, $ len doğru dosya boyutu sağlamaz.

Bu sorunu araştırma yaparken, ben bu yazı geldi: http://stackoverflow.com/questions/1334471/content-length-header-always-zero

Ben aynı sorunla karşılaşmış olduğumu görünüyor. Ben komut dosyası kullandığınızda, ben dosya üzerinde yığın halinde kodlama olsun ve hiçbir boyut içerik-uzunluk için ayarlanır. Ben bir şey dosyanın sonundan önce bir sıfır uzunlukta parça almak için onu lider, büyük yüklemeler yanlış gidiyor ki hipotesize ediyorum.

İşte başlıklar doğrudan bir istek gibi görünecektir:

http://www.grinderschool.com/videos/zfff5061b65ae00e8b21/KillsAids021.wmv

GET /videos/zfff5061b65ae00e8b21/KillsAids021.wmv HTTP/1.1
Host: www.grinderschool.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://www.grinderschool.com/phpBB3/viewtopic.php?f=14&p=29468
Cookie: style_cookie=printonly; phpbb3_7c544_u=2; phpbb3_7c544_k=44b832912e5f887d; phpbb3_7c544_sid=e8852df42e08cc1b2250300c2897f78f; __utma=174624884.2719561324781918700.1251850714.1270986325.1270989003.575; __utmz=174624884.1264524375.411.12.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=low%20stakes%20poker%20videos; phpbb3_cmviy_k=; phpbb3_cmviy_u=2; phpbb3_cmviy_sid=d8df5c0943863004ca40ef9c392d371d; __utmb=174624884.4.10.1270989003; __utmc=174624884
Pragma: no-cache
Cache-Control: no-cache

HTTP/1.1 200 OK
Date: Sun, 11 Apr 2010 12:57:41 GMT
Server: Apache/2.2.14 (Unix) mod_ssl/2.2.14 OpenSSL/0.9.8l DAV/2 mod_auth_passthrough/2.1 FrontPage/5.0.2.2635
Last-Modified: Sun, 04 Apr 2010 12:51:06 GMT
Etag: "eb42d6-7d9b843-48368aa6dc280"
Accept-Ranges: bytes
Content-Length: 131708995
Keep-Alive: timeout=10, max=30
Connection: Keep-Alive
Content-Type: video/x-ms-wmv

Ve işte onlar benim komut dosyası tarafından cevap istek gibi görünecektir:

http://www.grinderschool.com/download_video_test.php?t=KillsAids021&format=wmv

GET /download_video_test.php?t=KillsAids021&format=wmv HTTP/1.1
Host: www.grinderschool.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Cookie: style_cookie=printonly; phpbb3_7c544_u=2; phpbb3_7c544_k=44b832912e5f887d; phpbb3_7c544_sid=e8852df42e08cc1b2250300c2897f78f; __utma=174624884.2719561324781918700.1251850714.1270986325.1270989003.575; __utmz=174624884.1264524375.411.12.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=low%20stakes%20poker%20videos; phpbb3_cmviy_k=; phpbb3_cmviy_u=2; phpbb3_cmviy_sid=d8df5c0943863004ca40ef9c392d371d; __utmb=174624884.4.10.1270989003; __utmc=174624884

HTTP/1.1 200 OK
Date: Sun, 11 Apr 2010 12:58:02 GMT
Server: Apache/2.2.14 (Unix) mod_ssl/2.2.14 OpenSSL/0.9.8l DAV/2 mod_auth_passthrough/2.1 FrontPage/5.0.2.2635
X-Powered-By: PHP/5.2.11
Content-Disposition: attachment; filename=KillsAids021.wmv
Vary: Accept-Encoding
Content-Encoding: gzip
Keep-Alive: timeout=10, max=30
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: video/x-ms-wmv

Yani soru ... Ben düzgün komut işten indirme yapmak için ne yapabilirim mi? Olduğu gibi (ben hiçbir zaman tahmini yükleme hakkında hesaplanabilir ki böylece hiçbir dosyaboyu rapor olduğunu artık can sıkıcı ve bulmak olsa) Yine, kullanıcıların% 99 için, bu çalışıyor.

3 Cevap

Bu sizin GZIP sıkıştırma var. Bir içerik uzunluğunu belirtin ama bası açtığınızda, her şeyi sakızlar. Benim için bir kaç kere oldu: sizin komut kapatmayı deneyin.

Genellikle ile açmak istiyorum:

ob_start("ob_gzhandler");

... Yani sadece dışarı bu satırı comment. Sizin kodu değilse, şans yere php.ini dosyası veya apache.conf / conf.d ya da bir ayar var oldular.

Bu yardımcı olur umarım!

Content-Encoding: gzip

Hmm. Muhtemelen PHP'nin zlib.output_compression bunu yapıyor. (Apache mod_deflate benzemiyor.)

Kapatarak ve bu yığın halinde kodlama zorluyor buysa görmeye çalışın. Zaten son derece sıkıştırılmış WMV gibi bir filetype karşıdan sıkıştırmak istemiyorum.

Ancak, Yığın halinde kodlama sadece boyutu raporun eksikliği açıklar. Indir hala çalışması gerektiğini. Eğer zaman aşımı tarafından vurulduktan konum mümkündür (örn. PHP'nin set_time_limit, ya da Apache Timeout)?

Bu komut ise o zaman okur ve bir seferde biraz çıktılar readfile yerini function () işlevini kullanarak denediniz mi? Bunun arkasındaki mantık bir bellek sınırı bir yere ulaşmış ve başarısız olduğunu olabilir.

Dan http://php.net/manual/en/function.readfile.php:

function readfile_chunked ($filename) {
  $chunksize = 1*(1024*1024); // how many bytes per chunk
  $buffer = '';
  $handle = fopen($filename, 'rb');
  if ($handle === false) {
    return false;
  }
  while (!feof($handle)) {
    $buffer = fread($handle, $chunksize);
    print $buffer;
  }
  return fclose($handle);
} 

Ayrıca, gibi sık olarak çıktı temizlemek için deneyin.