HTTP üzerinden veri dowloading önce dosya boyutunu belirler

2 Cevap php

Bunu yapmak mümkün mü? Şu anda cURL kütüphanesini kullanarak PHP kodlama ediyorum ama bu değil, bir bütün olarak HTTP için de geçerlidir.

En belirgin yolu veri URL'ye bir HEAD isteği atma ve içerik-uzunluk başlığı okumak gibi geliyordu, ama sorun apache 2.0 dahil olmak üzere bazı sunucular KAFA isteklerine karşı Content-Length göndermek olmamasıdır ve zorunlu değil, çünkü orada hiçbir Orada tüm sunucular bile GET istek üzerine böyle bir bilgi ile cevap garanti.

I'm making the server download web pages specified by user input and store it on the server, but I do not want to let it download any requests only to find the file too large to be discarded after everything is downloaded to choke on the bandwidth from malicious requests. So I want to know the size of the content before the data is actually transfered, and reliably.

Genel durumlarda geri kalan tüm işleri eğer yanlış Content-Length göndererek kötü niyetli web sunucuları ve bu küçük garip vesilelerle vakaları, beni ilgilendirmiyor.

Kötü fikir şimdiye kadar aklımda aslında sadece GET isteği ile içerik indirmek ve transferi sırasında belirtilen boyut sınırını aşarsa, sadece bağlantıyı kesmek için, ama bu HTTP gibi genel bir protokol üzerinde çok çirkin bir çözüm gibi geliyor.

Daha iyi bir fikri var mı?

2 Cevap

Hayır, sunucular Bilgi kendilerini olmayabilir, çünkü onlar size hizmet etmek üzereyiz kaynağın boyutunu anlatmak zorunda değilsiniz. Yani hayır, evrensel bir yolu yok, ama evet o sağlanan her Content-length başlığı bakarak deneyebilirsiniz.

Ben aynı cevap arıyorum, sorunuzun tökezledi. Hiçbir gerçek cevabı henüz var gibi, ben kendim için bir uygulama yukarı kesmek ettik. Tabii ki, belirtilen tüm ikazlar hala geçerlidir, ve evet, bu "çirkin" varyantını kullanıyor - ama aslında verilere ulaşmak için tek yol var, bilgi var sağladı.

/**
 * Returns the size reported by the server, for the given URL, in bytes.
 *
 * Note this information may not be accurate, or may even be plain wrong.
 *
 * Also note, the return value is explicitly NOT converted to an integer, as
 * the remote file might be bigger than 2^31, which may mess up the number if
 * you are on a 32bit machine.
 *
 * @throws        InvalidArgumentException on unknown URL scheme
 * @throws        Exception when unable to connect
 * @param         string $url
 * @returns       int
 */
function getURLDownloadSize($url) {
    $parts = parse_url($url);

    if(isset($parts['port'])) {
        $port = $parts['port'];
    }
    else {
        $port = 80;
    }
    if($parts['scheme'] != 'http') {
        throw new \InvalidArgumentException('Scheme not supported');
    }

    $sock = fsockopen($parts['host'], $port, $errno, $errstr, 3);
    if(!$sock) {
        throw new \Exception(
            sprintf(
                'Unable to connect to host: %s',
                $errstr
            )
        );
    }
    stream_set_timeout($sock, 5);

    fwrite($sock, sprintf("GET %s HTTP/1.1\r\n", $parts['path']));
    fwrite($sock, sprintf("Host: %s\r\n",        $parts['host']));
    fwrite($sock,         "Connection: close\r\n"              );
    fwrite($sock,         "\r\n"                               );

    $data = fread($sock, 1024*20);
    fclose($sock);

    $matchresult = array();
    if (preg_match('/Content-Length:\s+(\d+)/', $data, $matchresult)) {
        return $matchresult[1];
    }
    return 0;
}