PDA

View Full Version : php | הורדת קובץ


Ron | CSite.co.il
07-11-08, 11:40
שלום,
יש לי בעיה קטנה בהורדת קובץ מהשרת אל המחשב בעזרת php.
אני מצליח להוריד את הקובץ בצורה מושלמת והכל,
הבעיה היחידה היא שצריך לחכות בעמוד ההורדה X זמן (בהתאם לגודל הקובץ),
אם מנסים להוריד קובץ של 14 מגה לדוגמא, צריך לחכות הרבה זמן עד שמופיע חלון ההורדה.
איך אפשר לעשות שזה יוריד ישר ?

הקוד:


// fix for IE catching or PHP bug issue
header("Pragma: public");
header("Expires: 0"); // set expiration time
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
// force download dialog
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
// use the Content-Disposition header to supply a recommended filename and
// force the browser to display the save dialog.
header("Content-Disposition: attachment; filename=".basename($download_file).";");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($local_file));


// open file stream
$file = fopen($local_file, "r");
while(!feof($file)) {
// send the current file part to the browser
print fread($file, round($download_rate * 1024));

// flush the content to the browser
flush();

// sleep one second
sleep(1);
}

לפי מה שבדקתי,
הבעיה היא שהקובץ עובר על הלולאה ורק אז מציג את חלון ההורדה (אחרי שהוא מסיים לעבור על כל הלולאה).

תודה רבה.

SniR-S
07-11-08, 12:48
נכון לעכשיו אני לומד PHP ואני בדיוק בשלב של הלולאות אם הבנתי נכון מהספר
בשביל לעשות את מה שאתה רוצה תצטרך להשתמש בלולאה do while.
שמה שהיא עושה בעצם זה בצע כל עוד..היא שונה מלולאת ה while בזה שהתנאי
שלה נבדק אחרי כל מעבר על הלולאה.

אז אם הבנתי נכון, אני חושב שזה מה שתצטרך לעשות,

// fix for IE catching or PHP bug issue
header("Pragma: public");
header("Expires: 0"); // set expiration time
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
// force download dialog
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
// use the Content-Disposition header to supply a recommended filename and
// force the browser to display the save dialog.
header("Content-Disposition: attachment; filename=".basename($download_file).";");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($local_file));


// open file stream
$file = fopen($local_file, "r");
do {
// send the current file part to the browser
print fread($file, round($download_rate * 1024));

// flush the content to the browser
flush();

// sleep one second
sleep(1);
} while(!feof($file));


אני מאוד מקווה שזה נכון ואני צודק (:

Ron | CSite.co.il
07-11-08, 13:32
תודה רבה על הניסיון לעזור,
אך כמובן שזה לא יפתור את הבעיה.

Shon12
07-11-08, 13:34
תודה רבה על הניסיון לעזור,
אך כמובן שזה לא יפתור את הבעיה.
למה שהפיתרון שלו לא יפתור את הבעיה?, כי אם לא - לא הבנתי מה הבעיה...

Ron | CSite.co.il
07-11-08, 13:37
הפתרון שלו לא יפתור את הבעיה מסיבה פשוטה,
רק שכל הדף php מסתיים מוצג חלון ההורדה,
כלומר הלולאה תבוצע ורק שהיא תסתים זה ידפיס את חלון ההורדה.

SniR-S
07-11-08, 14:01
בדקת?
מה שבעצם עשיתי פה הפכתי את לולאת ה while ל do while
שקודם הפעולה תבוצע ורק לאחר מכן היא בודקת אותה..
אם הבנתי נכון זה מה שרצית, השאלה היא אם זה פועל..(זה אמור לעבוד)

Ron | CSite.co.il
07-11-08, 14:02
כמו שהסברתי למעלה זו לא הבעיה (וכן בדקתי, אף על פי שידעתי שזה לא יעבוד),
הבעיה היא שקודם כל הסקריפט טוען את העמוד ועובר על כולו ורק לאחר מכן מציג את חלון ההורדה,
השאלה איך אפשר לעשות זאת אחרת.

tbm
07-11-08, 17:21
http://www.php.net/manual/en/function.flush.php
ולי זה יעזור לך...

vadimg88
07-11-08, 18:04
ה flush לא יעזור לו, הסיבה לכך היא פשוטה הגיוני שקובץ של מגה ירד מהר יותר מקובץ של 14 מגה. כדי להציג חלון הורדה הוא צריך לקרוא את כל הקובץ ובעזרת הכותרים המתאימים הוא מציג חלון הורדה במקום בעצם להציג את התוכן שלה קובץ שנקרא. זוהי פעולה נדרשת. מה שאתה יכול לעשות כדי למנוע את זה כדי שיציג את זה ישיר היא פעולת CACHE פעם אחת של הקובץ. לא משנה באיזה פונקציה תשתמש כדי לקרוא את הקובץ זה יקח זמן לקבצים גדולים.

פעם אחת תבצע שמירה של התוכן ב CACHE ולאחר מכן כל פעם שמשהו ינסה להוריד את הקובץ זה ישר יטען את זה מה CACHE במקום לקרוא את הכל ישירות. זה יחסוך המון זמן טעינה.

Shon12
07-11-08, 19:12
ה flush לא יעזור לו, הסיבה לכך היא פשוטה הגיוני שקובץ של מגה ירד מהר יותר מקובץ של 14 מגה. כדי להציג חלון הורדה הוא צריך לקרוא את כל הקובץ ובעזרת הכותרים המתאימים הוא מציג חלון הורדה במקום בעצם להציג את התוכן שלה קובץ שנקרא. זוהי פעולה נדרשת. מה שאתה יכול לעשות כדי למנוע את זה כדי שיציג את זה ישיר היא פעולת CACHE פעם אחת של הקובץ. לא משנה באיזה פונקציה תשתמש כדי לקרוא את הקובץ זה יקח זמן לקבצים גדולים.

פעם אחת תבצע שמירה של התוכן ב CACHE ולאחר מכן כל פעם שמשהו ינסה להוריד את הקובץ זה ישר יטען את זה מה CACHE במקום לקרוא את הכל ישירות. זה יחסוך המון זמן טעינה.
נשמע לי קצת לא הגיוני...
כל פעם שארצה שבנאדם יוריד מהאתר שלי קובץ גדול של-700Mb(סרט לדוגמא), אני אשמור במחשב של הבנאדם - 700Mb? נשמע ממש לא הגיוני. יוריד שני סרטים , אני אשמור 1.4Gb?
נשמע קצת מטורף...
אני בטוח שזו לא הדרך הנכונה לעשות את זה.

Ron | CSite.co.il
07-11-08, 19:13
מה שאתה אומר ממש לא הגיוני ואני בטוח שגם לא נכון.
לא הגיוני שאתר גמו ראפיד שמעלים אליו עשרות ג'יגות ביום פועל כך,
בטוח יש דרך אחרת שתגרום להוריד את הקובץ תוך כדי קריאה שלו.

vadimg88
07-11-08, 19:35
ה CACHE נשמר בשרת לא במחשב של המשתמש. ודיברנו על 14 מגה לא 700. לקבצים גדולים כמו 700 זה נושא אחר ומה שיש להם לא ממש תוכל לרכוש. אבל מחיפוש קצר מצאתי את זה:

http://blog.thinkphp.de/archives/136-Make-the-download-of-large-files-with-PHP-and-lighty-very-easy.html

שווה לך לנסות

SDF
07-11-08, 19:48
אהלן,
בדקתי את הסקריפט אצלי,
אצלי מופיע התיבה לשמירה בתחילת הלולאה.
בדקתי עם קובץ של 1.3G
בדקתי עם IE6 ו FF3.0.3 (אולי הבעיה בIE7 ?)

אתה מוזמן לראות בעצמך. (http://mate.nix.co.il/download/)

EidaN
07-11-08, 20:19
אהלן,
בדקתי את הסקריפט אצלי,
אצלי מופיע התיבה לשמירה בתחילת הלולאה.
בדקתי עם קובץ של 1.3G
בדקתי עם IE6 ו FF3.0.3 (אולי הבעיה בIE7 ?)

אתה מוזמן לראות בעצמך. (http://mate.nix.co.il/download/)

בדקתי על IE7 וגם שם פועל מצוין, כשהתיבה לשמירה נמצאת בתחילת הללואה.

Ron | CSite.co.il
07-11-08, 21:09
שיניתם משהו בקוד ? (מלבד נתיב הקובץ)

SDF
07-11-08, 21:16
עשיתי copy & paste:

<?php
$local_file = "sol-nv-b99-x86-dvd-iso-a.zip";
$download_file = "test.bin";
$download_rate = "10";

// fix for IE catching or PHP bug issue
header("Pragma: public");
header("Expires: 0"); // set expiration time
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
// force download dialog
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
// use the Content-Disposition header to supply a recommended filename and
// force the browser to display the save dialog.
header("Content-Disposition: attachment; filename=".basename($download_file).";");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($local_file));


// open file stream
$file = fopen($local_file, "r");
while(!feof($file)) {
// send the current file part to the browser
print fread($file, round($download_rate * 1024));

// flush the content to the browser
flush();

// sleep one second
sleep(1);
}
?>


גרסת PHP:

PHP 5.2.6 with Suhosin-Patch 0.9.6.2 (cgi-fcgi) (built: Sep 6 2008 02:21:32)
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies

Ron | CSite.co.il
07-11-08, 21:18
תודה רבה,
כנראה שהבעיה היא שאחרי הלולאה אני מבצע עוד מס' פעולות.