http://440hz.ru/trash/download/ Код (PHP): <? // 440hz $string = "Hello, world!"; $string .= "\t"; $string .= "I am a happy worm!" ; $string .= "\n"; if(isset($_SERVER['HTTP_USER_AGENT']) and strpos($_SERVER['HTTP_USER_AGENT'],'MSIE')) Header('Content-Type: application/force-download'); else Header('Content-Type: application/octet-stream'); Header('Accept-Ranges: bytes'); Header('Content-Length: '.strlen($string)); Header('Content-disposition: attachment; filename="products.txt"'); echo $string; exit(); ?>
это для Header('Content-Length: '.strlen($string)); что б броузер знал что ты длину контента в байтах передаешь
а Accept-Ranges указывает, что сервер может отдать любую часть файла с точностью до указанной величины.
440Hz Кстати, давно вот пытаюсь понять, как-же сделать скрипт, который умеет отдавать и по частям фаилы - с поддержкой докачки. Не просвятишь на этот счёт? За Header('Accept-Ranges: bytes'); спасибо, давно пытался найти, как браузеру указать размер фаила, что-бы он отображал сколько-же закачалось от общего размера.
dark-demon, IE6 (отнюдь еще не старый), получив octet-stream пытается показать свою исключительную грамотность и услужливость пользователям, путем самопального определения типа файла. То есть, например, картинки выдать на скачку не получится — они будут отрисовываться.
http://440hz.ru/trash/downloadpie/ Код (PHP): <? // 2007 (c) 440hz // отдаваемое файло $filename = 'queen.mp3'; // есл файла нет if (!file_exists($filename)) { header ("HTTP/1.0 404 Not Found"); exit; } // получим размер файла $fsize = filesize($filename); // дата модификации файла для кеширования $ftime = date("D, d M Y H:i:s T", filemtime($filename)); // смещение от начала файла $range = 0; // пробуем открыть $handle = @fopen($filename, "rb"); // если не удалось if (!$handle){ header ("HTTP/1.0 403 Forbidden"); exit; } // Если запрашивающий агент поддерживает докачку if ($_SERVER["HTTP_RANGE"]) { $range = $_SERVER["HTTP_RANGE"]; $range = str_replace("bytes=", "", $range); $range = str_replace("-", "", $range); // смещаемся по файлу на нужное смещение if ($range) { fseek($handle, $range); } } // если есть смещение if ($range) { header("HTTP/1.1 206 Partial Content"); } else { header("HTTP/1.1 200 OK"); } header("Content-Disposition: attachment; filename="{$filename}""); header("Last-Modified: {$ftime}"); header("Content-Length: ".($fsize-$range)); header("Accept-Ranges: bytes"); header("Content-Range: bytes {$range}-".($fsize - 1)."/".$fsize); // подправляем под IE что б не умничал if(isset($_SERVER['HTTP_USER_AGENT']) and strpos($_SERVER['HTTP_USER_AGENT'],'MSIE')) Header('Content-Type: application/force-download'); else Header('Content-Type: application/octet-stream'); while(!feof($handle)) { $buf = fread($handle,512); print($buf); } fclose($handle); ?> Код (Text): www(root):/usr/home/440hz#>wget -v -S -c "http://440hz.ru/trash/downloadpie/index.html" --17:28:41-- http://440hz.ru/trash/downloadpie/index.html => `index.html' Распознаётся 440hz.ru... 77.234.201.222 Устанавливается соединение с 440hz.ru|77.234.201.222|:80... соединение установлено. Запрос HTTP послан, ожидается ответ... HTTP/1.1 200 OK Date: Thu, 13 Dec 2007 14:09:20 GMT Server: Apache/2.0.59 (FreeBSD) PHP/5.2.2 with Suhosin-Patch X-Powered-By: PHP/5.2.2 Content-Disposition: attachment; filename="queen.mp3" Last-Modified: Thu, 13 Dec 2007 16:45:47 MSK Content-Length: 4201788 Accept-Ranges: bytes Content-Range: bytes 0-4201787/4201788 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Type: application/octet-stream Длина: 4 201 788 (4,0M) [application/octet-stream] 8% [=============> ] 374 604 20,58K/s ETA 02:18^C www(root):/usr/home/440hz#>wget -v -S -c "http://440hz.ru/trash/downloadpie/index.html" --17:29:00-- http://440hz.ru/trash/downloadpie/index.html => `index.html' Распознаётся 440hz.ru... 77.234.201.222 Устанавливается соединение с 440hz.ru|77.234.201.222|:80... соединение установлено. Запрос HTTP послан, ожидается ответ... HTTP/1.1 206 Partial Content Date: Thu, 13 Dec 2007 14:09:40 GMT Server: Apache/2.0.59 (FreeBSD) PHP/5.2.2 with Suhosin-Patch X-Powered-By: PHP/5.2.2 Content-Disposition: attachment; filename="queen.mp3" Last-Modified: Thu, 13 Dec 2007 16:45:47 MSK Content-Length: 3822840 Accept-Ranges: bytes Content-Range: bytes 378948-4201787/4201788 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Type: application/octet-stream Длина: 4 201 788 (4,0M), 3 822 840 (3,6M) осталось [application/octet-stream] 14% [++++++++++++++========> ] 597 150 35,92K/s ETA 01:57^C www(root):/usr/home/440hz#>wget -v -S -c "http://440hz.ru/trash/downloadpie/index.html" --17:29:51-- http://440hz.ru/trash/downloadpie/index.html => `index.html' Распознаётся 440hz.ru... 77.234.201.222 Устанавливается соединение с 440hz.ru|77.234.201.222|:80... соединение установлено. Запрос HTTP послан, ожидается ответ... HTTP/1.1 206 Partial Content Date: Thu, 13 Dec 2007 14:10:30 GMT Server: Apache/2.0.59 (FreeBSD) PHP/5.2.2 with Suhosin-Patch X-Powered-By: PHP/5.2.2 Content-Disposition: attachment; filename="queen.mp3" Last-Modified: Thu, 13 Dec 2007 16:45:47 MSK Content-Length: 3603190 Accept-Ranges: bytes Content-Range: bytes 598598-4201787/4201788 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Type: application/octet-stream Длина: 4 201 788 (4,0M), 3 603 190 (3,4M) осталось [application/octet-stream] 22% [+++++++++++++++++++++++============> ] 944 224 23,31K/s ETA 01:59^C Код (Text): 80.93.56.219 - - [13/Dec/2007:17:09:20 +0300] "GET /trash/downloadpie/index.html HTTP/1.0" 200 417792 "-" "Wget/1.10.2" 124 412680 80.93.56.219 - - [13/Dec/2007:17:10:30 +0300] "GET /trash/downloadpie/index.html HTTP/1.0" 206 385024 "-" "Wget/1.10.2" 146 379376 80.93.56.219 - - [13/Dec/2007:17:12:00 +0300] "GET /trash/downloadpie/index.html HTTP/1.0" 206 2629632 "-" "Wget/1.10.2" 146 2625224
Сейчас попробовал выполнить скрипт указанный в начале темы на локалхосте и все нормально заработало, а на сервере хостера обрабатывается не правильно. При сохранении вместо имени файла, который указан в скрипте, появляется имя файла скрипта. В чем может быть проблема и как ее устранить?
Есть сервер на котором расположен сайт mysite.ru и есть другой сервер на котором расположены архивы myarhive.ru. Скрипт расположен на mysite.ru Пользователю выдаётся ссылка вида http://mysite.ru/sms/load.php?DDFA6655E6ACE284AC47D1027BB84DE4 1. При скачивании архива через браузер (скачивание идёт в один поток) по кодированной ссылке всё проходит нормально, архив скачивается полностью распаковывается и всё работает, но не работает докачка, а это важно. 2. При скачивании с помощью FlashGet (несколько потоков) теряется часть файлов и папок находящихся внутри архива. При этом размер скачанного архива тот же, что и у исходного. Так по крайней мере показывает Тотал Commander. 3. Пробовал скачивать по прямой ссылке вида http://myarhive.ru/arhive1.rar и сравнивал передаваемые заголовки с заголовками, полученными при скачивании по п. 2. Формируемые заголовки ИДЕНТИЧНЫ. Перепробовал разные варианты скриптов, какие нашёл на форумах и мануалах, ничего не помогает. Подскажите, что сделано не верно, где кроется ошибка. Буду очень признателен. Исходный код (часть его отвечающая за закачку): Код (PHP): <? // опущена часть кода // Подключаем сокет к серверу, т.к. сервер удалённый // Берём заголовки и отключаемся // $info - ассоциативный массив заголовков // $headers - строка заголовков // $tab - размер заголовков (в байтах) // myarhive.ru - здесь лежат архивы $fp = fsockopen ("myarhive.ru", 80, $errno, $errstr, 30); if(!$fp){ echo "$errstr ($errno)<br>\n"; }else{ fputs ($fp, "GET /$name HTTP/1.0\r\nHost: myarhive.ru\r\n\r\nContent-Type: application/rar\r\nConnection: Close"); $info = Array(); $headers = ''; $tab = 0; for($i = 0; $i < 9; $i++){ $str = fgets ($fp,1024); $tab += strlen($str); $str = substr($str, 0, strlen($str) - 2); $headers .= $str ."\n"; $tmp = explode(": ", $str); $info[$tmp[0]] = $tmp[1]; } fclose ($fp); } // Передаём пользователю заголовки // Принимаем файл с сервера и отдаём его юзеру $filename = "http://myarhive.ru/".$name; //$name - имя архива $fsize = $info['Content-Length']; $modified = $info['Last-Modified']; $fd = @fopen($filename, "rb"); if (!$fd){ header ("HTTP/1.0 403 Forbidden"); exit; } // Если запрашивающий агент поддерживает докачку if ($_SERVER["HTTP_RANGE"]) { $range = $_SERVER["HTTP_RANGE"]; $range = str_replace("bytes=", "", $range); $range = str_replace("-", "", $range); $range = intval($range); fseek($fd, $range); // передаю заголовки полученные через сокет (часть из них будет ниже изменена) foreach($info as $key => $value){ header($key.": ".$value); } // Формирую заголовки необходимые для докачки header("HTTP/1.1 206 Partial Content"); header ("Content-Type: application/x-rar-compressed"); header("Accept-Ranges: bytes"); header("Content-Length: ".($fsize-$range)); header("Content-Range: bytes $range-".($fsize -1)."/".$fsize); header("Content-Disposition:attachment; filename=".$name); } else{ header("HTTP/1.1 200 OK"); header ("Content-Type: application/x-rar-compressed"); header("Content-Disposition:attachment; filename=".$name); header("Content-Length: ".$fsize); header("Last-Modified: ".$modified); header("Accept-Ranges: bytes"); } $buffer = ''; while (!feof($fd)) { set_time_limit(0); $buffer = fgets($fd, 4096); print $buffer; flush(); } fclose($fd); // опущена часть кода ?>
Для примера полученные заголовки: 1-й канал Скачиваем по ссылке http://myarhive.ru/arhive1.rar Код (Text): Fri May 23 11:39:26 2008 HTTP/1.1 200 OK Fri May 23 11:39:26 2008 Date: Fri, 23 May 2008 07:32:41 GMT Fri May 23 11:39:26 2008 Server: Apache Fri May 23 11:39:26 2008 Last-Modified: Thu, 22 May 2008 16:15:17 GMT Fri May 23 11:39:26 2008 ETag: "4a71d6-23f141-48359c15" Fri May 23 11:39:26 2008 Accept-Ranges: bytes Fri May 23 11:39:26 2008 Content-Length: 2355521 Fri May 23 11:39:26 2008 Connection: close Fri May 23 11:39:26 2008 Content-Type: application/x-rar-compressed Скачиваем по ссылке http://mysite.ru/sms/load.php?DDFA6655E6ACE284AC47D1027BB84DE4 Код (Text): Fri May 23 11:38:16 2008 HTTP/1.1 200 OK Fri May 23 11:38:16 2008 Server: nginx/0.5.7 Fri May 23 11:38:16 2008 Date: Fri, 23 May 2008 07:38:09 GMT Fri May 23 11:38:16 2008 Content-Type: application/rar Fri May 23 11:38:16 2008 Connection: close Fri May 23 11:38:16 2008 X-Powered-By: PHP/4.4.4 Fri May 23 11:38:16 2008 Last-Modified: Fri, 23 May 2008 07:38:09 GMT Fri May 23 11:38:16 2008 ETag: "4a71d6-23f141-48359c15" Fri May 23 11:38:16 2008 Accept-Ranges: bytes Fri May 23 11:38:16 2008 Content-Length: 2355521 Fri May 23 11:38:16 2008 Content-Disposition: attachment; filename=testarhiv.rar Fri May 23 11:38:16 2008 Content-transfer-encoding: binary 2-й канал (возможна докачка): Скачиваем по ссылке http://myarhive.ru/arhive1.rar Код (Text): Fri May 23 11:39:27 2008 HTTP/1.1 206 Partial Content Fri May 23 11:39:27 2008 Date: Fri, 23 May 2008 07:32:43 GMT Fri May 23 11:39:27 2008 Server: Apache Fri May 23 11:39:27 2008 Last-Modified: Thu, 22 May 2008 16:15:17 GMT Fri May 23 11:39:27 2008 ETag: "4a71d6-23f141-48359c15" Fri May 23 11:39:27 2008 Accept-Ranges: bytes Fri May 23 11:39:27 2008 Content-Length: 1884417 Fri May 23 11:39:27 2008 Content-Range: bytes 471104-2355520/2355521 Fri May 23 11:39:27 2008 Connection: close Fri May 23 11:39:27 2008 Content-Type: application/x-rar-compressed Скачиваем по ссылке http://mysite.ru/sms/load.php?DDFA6655E6ACE284AC47D1027BB84DE4 Код (Text): Fri May 23 11:38:19 2008 HTTP/1.1 206 Partial Content Fri May 23 11:38:19 2008 Server: nginx/0.5.7 Fri May 23 11:38:19 2008 Date: Fri, 23 May 2008 07:38:12 GMT Fri May 23 11:38:19 2008 Content-Type: application/rar Fri May 23 11:38:19 2008 Connection: close Fri May 23 11:38:19 2008 X-Powered-By: PHP/4.4.4 Fri May 23 11:38:19 2008 Last-Modified: Fri, 23 May 2008 07:38:12 GMT Fri May 23 11:38:19 2008 ETag: "4a71d6-23f141-48359c15" Fri May 23 11:38:19 2008 Accept-Ranges: bytes Fri May 23 11:38:19 2008 Content-Length: 1884417 Fri May 23 11:38:19 2008 Content-Range: bytes 471104-2355520/2355521 Fri May 23 11:38:19 2008 Content-Disposition: attachment; filename=testarhiv.rar Fri May 23 11:38:19 2008 Content-transfer-encoding: binary Как видно из приведённого кода, заголовки отвечающие за докачку идентичны, совпадает до байта. По остальным каналам, так же полное совпадение.
Можно данный скрипт преписать чтобы скачивать архив Есть задача скачивать эксель файл с товарами и архив с фото к товарам. Проблему ехселя я решил совместно а вот смачивание недотающих фоток не могу. Скрипт сверяет базу свою с базой источника и должен скачать недостающие фотки. Есть прямой путь к картинке но не какие манипуляции и попытки получить хотябы вес картинки не дали результата. Подскажите есть ли решение чтобы не мучаться?
Кстати мысли в слух. В опере .rar некоректно пытается скачатся, открывается как .txt (по дефолту опера незнает такого расширения). А вот с zip и 7z работает на ура.