سؤال

على موقع ويب يعتمد على PHP، أريد أن أرسل للمستخدمين حزمة تنزيل بعد ملء نموذج قصير.يجب أن يكون التنزيل الذي يبدأه الموقع مشابهًا لمواقع مثل download.com، التي تقول "سيبدأ التنزيل خلال دقيقة واحدة".

زوج من النهج الممكنة أعرف توافق المتصفح (استنادًا إلى اختبار سريع):

1) افعل أ window.open مشيرا إلى الملف الجديد.

- FireFox 3 blocks this.  
 - IE6 blocks this.  
 - IE7 blocks this.

2) قم بإنشاء إطار iframe يشير إلى الملف الجديد.

- FireFox 3 seems to think this is OK. (Maybe it's because I already accepted it once?)  
 - IE6 blocks this.  
 - IE7 blocks this.

How can I do this so that at least these three browsers will not object? 

علاوة:هل هناك طريقة لا تتطلب عبارات شرطية للمتصفح؟

(أعتقد أن download.com يستخدم كلتا الطريقتين بشكل مشروط، لكن لا يمكنني تشغيل أي منهما.)

الردود والتوضيحات:

Q: "Why not point the current window to the file?"  
A: That might work, but in this particular case, I want to show them some other content while their download starts - for example, "would you like to donate to this project?"

تحديث:لقد تخليت عن هذا النهج.انظر إجابتي أدناه لأسباب.

هل كانت مفيدة؟

المحلول

يمكنك أيضًا إجراء تحديث تعريفي، وهو ما تدعمه معظم المتصفحات.يضع موقع Download.com واحدًا في علامة noscript.

<meta http-equiv="refresh" content="5;url=/download.php?doc=123.zip"/>

نصائح أخرى

تحديث:لقد قررت التخلي عن هذا النهج، وبدلاً من ذلك فقط أقدم للمستخدم رابطًا للملف الفعلي.تفكيري هو هذا:

تم حظر محاولاتي الأولية للتنزيل الذي بدأه الخادم بواسطة المتصفح.هذا جعلني أفكر:"المتصفح صحيح.كيف هو - هي هل تعلم أن هذا تنزيل شرعي؟هو - هي يجب حظر التنزيل الذي لم يبدأه المستخدم بشكل واضح."

يمكن لأي طريقة يمكنني استخدامها للتنزيل الذي يبدأه الخادم أيضًا يمكن استخدامها من قبل شخص يريد إرسال البرامج الضارة.لذلك، يجب أن تتم التنزيلات فقط عندما يطلب المستخدم الملف على وجه التحديد من خلال النقر على الرابط الخاص به.

لك الحرية في عدم الموافقة، وإذا كنت لا تزال ترغب في بدء التنزيل، نأمل أن يساعدك هذا الموضوع على القيام بذلك.

عادةً ما يكون لدي برنامج نصي PHP يقوم بإخراج الملف مباشرةً إلى المتصفح باستخدام نوع المحتوى المناسب

if(file_exists($filename)) {
    header("Pragma:  public");
    header("Expires:  0");
    header("Cache-Control:  must-revalidate, pre-check=0");
    header("Cache-Control:  private", false);
    header("Content-Type:  " . $content-type);
    header("Content-Disposition:  attachment; filename=\"" . basename($filename) . "\";" );
    header("Content-Transfer-Encoding:  binary");
    header("Content-Length:  " . filesize($filename));

    readfile("$filename");
}else{
    print "ERROR:  the file " . basename($filename) . " could not be downloaded because it did not exist.";
}

العيب الوحيد هو أنه نظرًا لأن هذا يعين رأس HTTP، فقد تم استدعاؤه قبل أن يكون لديك أي مخرجات أخرى.

ولكن يمكن أن يكون لديك رابط إلى صفحة تنزيل PHP وسيؤدي ذلك إلى ظهور مربع تنزيل منبثق في المتصفح دون الإضرار بمحتوى الصفحة الحالية.

إحدى المشاكل هي أنك قد تواجه مشكلات مع IE (الإصدار 6 على وجه الخصوص) إذا لم يتم إعداد الرؤوس "بشكل صحيح".

تأكد من تعيين نوع المحتوى الصحيح، ولكن ضع في اعتبارك أيضًا تعيين خيارات ذاكرة التخزين المؤقت لـ IE (على الأقل) على ذلك يسمح التخزين المؤقت.إذا كان الملف واحدًا، فيمكن للمستخدم فتحه بدلاً من حفظه (على سبيل المثال.مستند MS Word) تحتاج الإصدارات المبكرة من IE إلى تخزين الملف مؤقتًا، حيث تقوم بتسليم الطلب "الفتح" إلى التطبيق المناسب، مع الإشارة إلى الملف الذي تم تنزيله في ذاكرة التخزين المؤقت.

هناك أيضًا مشكلة ذات صلة، إذا كانت ذاكرة التخزين المؤقت لمستخدم IE6 ممتلئة، فلن يحفظ الملف بشكل صحيح (وبالتالي عندما يحصل التطبيق المناسب على اليد لفتحه، فسوف يشكو من تلف الملف.

قد ترغب أيضًا في تشغيل أي إجراءات gzip على التنزيلات أيضًا (لـ IE)

يواجه كل من IE6/IE7 مشكلات تتعلق بالتنزيلات الكبيرة (على سبيل المثال.4.x Gigs...) ليس سيناريو محتملًا نظرًا لأن IE ليس لديه حتى مدير تنزيل، ولكن هناك شيء يجب أن تكون على دراية به.

أخيرًا، لا يتعامل IE6 أحيانًا بشكل جيد مع "دفعة" التنزيل إذا تم بدئها من داخل إطار iframe متداخل.لست متأكدًا تمامًا من سبب المشكلة، ولكني أجد أنه من الأسهل مع IE6 تجنب هذا السيناريو.

هوي!

@ ناثان:قررت أن أفعل ذلك بالضبط:اطلب من "getfile.php" تحميل جميع الأشياء الضرورية ثم قم بإجراء

header("Location: ./$path/$filename");

للسماح للمتصفح نفسه والقيام مباشرة بما يعتقد أنه صحيح مع الملف.هذا حتى يعمل بشكل جيد في الأوبرا معي.

ولكن هذا سيكون مشكلة في البيئات، حيث لا يسمح بالوصول المباشر إلى الملفات، في هذه الحالة سيكون عليك إيجاد طريقة مختلفة!(شكرًا لـ Discordia، ملفاتي هي ملفات PDF عامة!)

مع أطيب التحيات، باستي

ماذا عن تغيير الموقع للإشارة إلى الملف الجديد؟(على سبيل المثالعن طريق تغيير window.location)

لقد قمت دائمًا بإنشاء إطار iframe يشير إلى الملف.

<iframe src="/download.exe" frameborder="0" height="0" width="0"><a href="/download.exe">Click here to download.</a></iframe>

فيما يتعلق بعدم توجيه النافذة الحالية إلى التنزيل.في تجربتي، لا يزال بإمكانك إظهار صفحة "الرجاء التبرع"، نظرًا لأن التنزيلات (طالما أنها ترسل الرؤوس الصحيحة) لا تقوم فعليًا بتحديث نافذة المتصفح.أفعل ذلك من أجل عمليات تصدير ملف CSV على أحد مواقعي، وبقدر ما يتعلق الأمر بالمستخدم، تظهر نافذة ملف آمن.لذلك أوصي بإعادة توجيه تعريفية بسيطة كما أظهر Soldarnal.

فقط للتلخيص، لديك هدفين:

  1. بدء عملية التنزيل
  2. تظهر للمستخدم صفحة تحتوي على خيارات التبرع

ولتحقيق ذلك سأقوم بما يلي:

عندما يرسل المستخدم النموذج، يحصل على الصفحة الناتجة مع خيارات التبرع ونص يقول أن التنزيل سيبدأ خلال 5 ثوانٍ.وفي القسم الرئيسي لهذه الصفحة قمت بوضع كود META كما قال Soldarnal:<meta http-equiv="refresh" content="5;url=/download.php?doc=123.zip>

و هذا كل شيء.

<a href="normaldownload.zip" onclick="use_dhtml_or_ajax_to_display_page()">

لا تتأثر الصفحة الحالية إذا تم حفظ التنزيل.فقط تأكد من عدم فتح التنزيل في نفس النافذة (نوع MIME المناسب أو Content-Disposition) وستكون قادرًا على إظهار أي شيء.

رؤية المزيد من الإجابة الكاملة

يمكنك استخدام Javascript/jQuery لبدء التنزيل.إليك مثالًا - يمكنك التخلص من طلب Ajax واستخدام كتلة setTimeout() فقط.

$("btnDownloadCSV").on('click', function() {
    $.ajax({
        url: "php_backend/get_download_url",
        type: 'post',
        contentType: "application/x-www-form-urlencoded",
        data: {somedata: "somedata"},
        success: function(data) {
            // If iFrame already exists, remove it.
            if($("[id^='iframeTempCSV_"]).length) { 
                $("[id^='iframeTempCSV_"]).remove();
            }
            setTimeout(function() {
                //  If I'm creating an iframe with the same id, it will permit download only the first time.
                // So randHashId appended to ID to trick the browser.
                var randHashId = Math.random().toString(36).substr(2);
                // Create a fresh iFrame for auto-downloading CSV
                $('<iframe id="iframeTempCSV_'+randHashId+'" style="display:none;" src="'+data.filepath+'"></iframe>').appendTo('body');
            }, 1000);
        },
        error: function(xhr, textStatus, errorThrown) {
           console.error("Error downloading...");
       }
    });
});
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top