PDA

View Full Version : مشکلات Mime Types و Download



microsoftsat
دوشنبه 21 اسفند 1385, 14:43 عصر
با سلام


کد زیر رو به عنوان مثال نوشته ام تا به بررسی اون بپردازیم:



$file = "test.zip";
$ext = strtolower(substr(strrchr($file,"."),1));

switch( $ext )
{
case "doc" : $type = "application/msword"; break;
case "dll" :
case "bin" :
case "exe" : $type = "application/octet-stream"; break;
case "pdf" : $type = "application/pdf"; break;
case "ppt" : $type = "application/vnd.ms-powerpoint"; break;
case "swf" : $type = "application/x-shockwave-flash"; break;
case "tar" : $type = "application/x-tar"; break;
case "zip" : $type = "application/zip"; break;
case "mid" : $type = "audio/midi"; break;
case "mp3" : $type = "audio/mpeg"; break;
case "ram" : $type = "audio/x-pn-realaudio"; break;
case "bmp" : $type = "image/bmp"; break;
case "gif" : $type = "image/gif"; break;
case "jpg" : $type = "image/jpeg"; break;
case "png" : $type = "image/png"; break;
case "tiff" : $type = "image/tiff"; break;
case "mpg" : $type = "video/mpeg"; break;
case "avi" : $type = "video/x-msvideo"; break;

default: $type = "application/force-download";
}

header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Type: $type");
$temp = "Content-Disposition: attachment; filename=".$file.";";
header($temp);
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($file));
readfile($file);







مشکلات:

1- اگر بخواهیم فایل هایی با پسوند جدید "xxx" داشته باشیم که قابل دانلود از طریق کد ذکر شده باشد، چه اعمالی را باید انجام دهیم؟
کافیست فقط پسوند جدید و "application/force-download" را در case بگذاریم؟
آیا افزودن Mime Type مربوطه در سرور لازم است؟


2- این کد در Download Accelerator درست کار نمی کند و فایل دانلود شده با نام "Unknown" خواهد بود (که پسوندش مشخص نیست)! در ضمن امکان resume رو هم ندارد!
مشکل کجاست؟


3- آیا اگر برای تمامی پسوند ها از "application/force-download" استفاده کنیم مشکلی پیش می آید؟



متشکرم،
سربلند باشید.

oxygenws
دوشنبه 21 اسفند 1385, 17:14 عصر
اول از همه اینو بخون (تا آخر!!!)
http://barnamenevis.org/forum/showthread.php?t=48653

۲- بهتره اطلاعاتت رو در زمینه http بیشتر کنی... تقریبا هیچی نمی دونی.
مسلما resume نمی شه!! مگر اینکه با PHP بشینی (تقریبا) یک وب سرور بنویسی!!!

۳- تست کن.

microsoftsat
دوشنبه 21 اسفند 1385, 18:47 عصر
اول از همه اینو بخون (تا آخر!!!)
http://barnamenevis.org/forum/showthread.php?t=48653


همشو ( تا آخر آخرش!) خوندم! (البته یعنی قبلا خونده بودم) :چشمک:
اما خوب جوابم رو نگرفتم!




۲- بهتره اطلاعاتت رو در زمینه http بیشتر کنی... تقریبا هیچی نمی دونی.
مسلما resume نمی شه!! مگر اینکه با PHP بشینی (تقریبا) یک وب سرور بنویسی!!!


یعنی نمی خوای نجاتم بدی!!؟ :بامزه:
(شاید یکی نداشته باشه!!!)


4- پیشنهادی برای غیر قابل دسترسی و دانلود بودن فایل ها از دید مثلا کاربران غیر عضو ندارید؟



ممنونم :لبخندساده:

oxygenws
دوشنبه 21 اسفند 1385, 21:24 عصر
۲- حسام جان... نه تنها نجاتت نمی دم بلکه سیفون رو هم می کشم... خودت برو RFC مربوط به HTTP رو پیدا کن و مطالعه اش کن. :بامزه:

۴- می تونی فایل temp بسازی!!! که مثلا بعد از ۲ ساعت اکسپایر بشه.


موفق باشی :)

ali_sed
شنبه 26 اسفند 1385, 01:45 صبح
at first one advise to Jon's post (09-Mar-2006 01:38)
the "function downloadFile ($file, $mimetype)" can NOT resume downloads.
the function sent every time the same file just with different header informations.

this function will work
<?php
function output_file($file,$name)
{
//do something on download abort/finish
//register_shutdown_function( 'function_name' );
if(!file_exists($file))
die('file not exist!');
$size = filesize($file);
$name = rawurldecode($name);

if (ereg('Opera(/| )([0-9].[0-9]{1,2})', $_SERVER['HTTP_USER_AGENT']))
$UserBrowser = "Opera";
elseif (ereg('MSIE ([0-9].[0-9]{1,2})', $_SERVER['HTTP_USER_AGENT']))
$UserBrowser = "IE";
else
$UserBrowser = '';

/// important for download im most browser
$mime_type = ($UserBrowser == 'IE' || $UserBrowser == 'Opera') ?
'application/octetstream' : 'application/octet-stream';
@ob_end_clean(); /// decrease cpu usage extreme
header('Content-Type: ' . $mime_type);
header('Content-Disposition: attachment; filename="'.$name.'"');
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header('Accept-Ranges: bytes');
header("Cache-control: private");
header('Pragma: private');

///// multipart-download and resume-download
if(isset($_SERVER['HTTP_RANGE']))
{
list($a, $range) = explode("=",$_SERVER['HTTP_RANGE']);
str_replace($range, "-", $range);
$size2 = $size-1;
$new_length = $size-$range;
header("HTTP/1.1 206 Partial Content");
header("Content-Length: $new_length");
header("Content-Range: bytes $range$size2/$size");
}
else
{
$size2=$size-1;
header("Content-Length: ".$size);
}
$chunksize = 1*(1024*1024);
$this->bytes_send = 0;
if ($file = fopen($file, 'r'))
{
if(isset($_SERVER['HTTP_RANGE']))
fseek($file, $range);
while(!feof($file) and (connection_status()==0))
{
$buffer = fread($file, $chunksize);
print($buffer);//echo($buffer); // is also possible
flush();
$this->bytes_send += strlen($buffer);
//sleep(1);//// decrease download speed
}
fclose($file);
}
else
die('error can not open file');
if(isset($new_length))
$size = $new_length;
die();
}
?>

ali_sed
شنبه 26 اسفند 1385, 01:54 صبح
I've created script that gives users ability to download files from closed directory. It supports multithread download and download resuming

<?php
$fname = $_GET['file'];
$fpath = "downloads/$fname";
$fsize = filesize($fpath);
$bufsize = 20000;

if(isset($_SERVER['HTTP_RANGE'])) //Partial download
{
if(preg_match("/^bytes=(\\d+)-(\\d*)$/", $_SERVER['HTTP_RANGE'], $matches)) { //parsing Range header
$from = $matches[1];
$to = $matches[2];
if(empty($to))
{
$to = $fsize - 1; // -1 because end byte is included
//(From HTTP protocol:
// 'The last-byte-pos value gives the byte-offset of the last byte in the range; that is, the byte positions specified are inclusive')
}
$content_size = $to - $from + 1;

header("HTTP/1.1 206 Partial Content");
header("Content-Range: $from-$to/$fsize");
header("Content-Length: $content_size");
header("Content-Type: application/force-download");
header("Content-Disposition: attachment; filename=$fname");
header("Content-Transfer-Encoding: binary");

if(file_exists($fpath) && $fh = fopen($fpath, "rb"))
{
fseek($fh, $from);
$cur_pos = ftell($fh);
while($cur_pos !== FALSE && ftell($fh) + $bufsize < $to+1)
{
$buffer = fread($fh, $bufsize);
print $buffer;
$cur_pos = ftell($fh);
}

$buffer = fread($fh, $to+1 - $cur_pos);
print $buffer;

fclose($fh);
}
else
{
header("HTTP/1.1 404 Not Found");
exit;
}
}
else
{
header("HTTP/1.1 500 Internal Server Error");
exit;
}
}
else // Usual download
{
header("HTTP/1.1 200 OK");
header("Content-Length: $fsize");
header("Content-Type: application/force-download");
header("Content-Disposition: attachment; filename=$fname");
header("Content-Transfer-Encoding: binary");

if(file_exists($fpath) && $fh = fopen($fpath, "rb")){
while($buf = fread($fh, $bufsize))
print $buf;
fclose($fh);
}
else
{
header("HTTP/1.1 404 Not Found");
}
}
?>

راستی کمی دقت کن که کاربران از طریق این فایل به همه فایل هات دسترسی نداشته باشند.مثلا از نام فایل هات رو در یک جدول قرار بده و به هر کدام یه کد اختصاص بده و اون کد را به این فایل بفرست و با استخراج نام فایل مربوط به این کد از دیتا بیس فایل را برا ی کاربر ارسال کن اگه سوالی بود بازم بپرس البته اگه بیام و بتونم جواب بدم دریغ نمی کنم.

microsoftsat
شنبه 26 اسفند 1385, 14:02 عصر
ali_sed از پاسخ شما بسیار ممنونم.

تابع output_file که همان مشکل DAP را دارد. (با Download accelerator به نام اصلی فایل دانلود نمیشه!)


کد دوم:
این کد رو قبلا در http://www.php.net/manual/en/function.header.php#65667 دیده بودم.
میشه در مورد اولین if آن توضیح دهید؟ (فکر کنم همیشه else اجرا میشه!)


متشکرم.

ali_sed
دوشنبه 28 اسفند 1385, 18:30 عصر
خواهش می کنم، دوست عزیز اول هر کد توضیحاتش هست، کد اول قابلیت resume را ندارد، درست مثل rapidshare.com و فایل نیز بصورت یک تیکه دانلود میشه.ولی کد دوم امکان resume و همچنین multithread downloading یا به عبارتی چند قسمت کردن فایل و دانلود آن را دارد و شرط اول هم به این دلیل بکار می رود،نرم افزار دانلود range های مورد نظر را به برنامه ارسال می کند به عنوان مثال از بایت 1000 تا 2200 فایل را درخواست می کند و برنامه نیز این بخش از فایل را برای دانلود منیجر ارسال می کند.

راستی اگه تمایل داری که از طرز کارش بهتر سردربیاری بهتره از flashget برای دانلود استفاده کنی و به کدهایی که برای سرور جهت دریافت فایل ارسال می کنه توجه کنی pause کن و دوباره resume کن و باز به کدهای ارسال شده توجه کن اگه بصورت لوکال این کارها را انجام می دی بهتره که یک فایل حجیم را دانلود کنی که سریع دانلود نشه.

ali_sed
سه شنبه 29 اسفند 1385, 13:47 عصر
اومدم ببینم بازم سوالی بی جواب مونده یا نه که دیدم هنوز مراجع نکردی.
راستی Msat یه اشاره به نام فایل دانلود شده کردی گفتم اینم بگم که در عبارت زیر می توانی نام فایل دانلود شده را هرچی میخوای بزاری:


header("Content-Disposition: attachment; filename=$fname");

به جای $fname هر نامی که می خوای می توانی بزاری.

sweb
شنبه 18 فروردین 1386, 02:08 صبح
آیا میشه تکنیک مخفی کردن لینک فایل رو در مورد یه سرور دیگه پیاده کرد. یعنی لینک فایل از یه سرور دیگه باشه ولی مسیر دانلود از سروری باشه که کد توش اجرا میشه ؟ :خجالت: