कैसे PHP के साथ फ़ाइल डाउनलोड को मजबूर करने के लिए


122

मुझे PHP के साथ एक वेब पेज पर जाने वाले उपयोगकर्ता पर एक फ़ाइल डाउनलोड करने की आवश्यकता है। मुझे लगता है कि इसके साथ कुछ करना है file_get_contents, लेकिन यह सुनिश्चित नहीं है कि इसे कैसे निष्पादित किया जाए।

$url = "http://example.com/go.exe";

किसी फ़ाइल को डाउनलोड करने के बाद header(location)उसे दूसरे पेज पर रीडायरेक्ट नहीं किया जाता है। बस रुक जाती है।



जवाबों:


232

अंतर्निहित PHP फ़ंक्शन रीडफ़ाइल के बारे में डॉक्स पढ़ें

$file_url = 'http://www.myremoteserver.com/file.exe';
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary"); 
header("Content-disposition: attachment; filename=\"" . basename($file_url) . "\""); 
readfile($file_url); 

अपनी फ़ाइल एप्लिकेशन / ज़िप, एप्लिकेशन / पीडीएफ आदि के आधार पर उचित सामग्री प्रकार को जोड़ना सुनिश्चित करें - लेकिन केवल तभी जब आप सहेजे गए संवाद को ट्रिगर नहीं करना चाहते हैं।


6
क्यों जरूरी है?
जॉन

मेरा मतलब है कि अगर इसके अलावा .exe फ़ाइल केवल की तुलना में है। तो यह ठीक काम करना चाहिए।
गड्ढे खोदने वाला

7
फ्लश करना न भूलें; ;-) ob_clean (); फ्लश (); / * से पहले * / readfile ($ file_url);
ऐश

तो अगर आपके पास 10GB बड़ी फाइल है तो वह पूरी फाइल लोड करने की कोशिश करता है?
GDY

बाहर निकलने () को किसी भी संभावित समस्या से बचने के लिए अंत में बुलाया जाना चाहिए (अनुभव से बोलना :-)
ykay का कहना है कि मोनिका

42
<?php
$file = "http://example.com/go.exe"; 

header("Content-Description: File Transfer"); 
header("Content-Type: application/octet-stream"); 
header("Content-Disposition: attachment; filename=\"". basename($file) ."\""); 

readfile ($file);
exit(); 
?>

या, जब फ़ाइल ब्राउज़र के साथ खोलने योग्य नहीं है, तो आप सिर्फ Locationहेडर का उपयोग कर सकते हैं :

<?php header("Location: http://example.com/go.exe"); ?>

1
आपके हेडर में फ़ाइलनाम नहीं होना चाहिए $file(जिसमें http हिस्सा होता है) लेकिन एक वैध फ़ाइल नाम।
फैबियो

1
कोई एप्लिकेशन / बल-डाउनलोड मीडिया प्रकार नहीं है; का उपयोग आवेदन / ओकटेट धारा बजाय।
गंबो

बहुत अच्छा काम करता है! लेकिन संग्रहीत फ़ाइल नाम के लिए 'जोड़ता है। कृपया उपयोग करें: फ़ाइल नाम = "। बेसनैम ($ फ़ाइल));
harry4516

@ harry4516 अपनी खोज के अनुसार संशोधित
मारेक सेबरा

मेरे लिए png छवि के मामले में प्रिय काम नहीं। धन्यवाद।
कमलेश

40
header("Content-Type: application/octet-stream");
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"file.exe\""); 
echo readfile($url);

सही है

या exe प्रकार की फ़ाइलों के लिए बेहतर है

header("Location: $url");

@ फैबियो:
उत्पत्ति

यह सुपर आसान था। इसने काम कर दिया। तब के लिए फ़ाइल-Get_contents क्या है? बस उत्सुक। धन्यवाद।
जॉन

इसे अपने सर्वर पर डाउनलोड करने के लिए
उत्पत्ति

10
वापसी मूल्य के रूप में 'रीडफ़ाइल ()' से पहले बस 'इको' को हटा दें क्योंकि फ़ाइल से पढ़ी गई बाइट्स की संख्या लौटाता है। यदि कोई त्रुटि होती है, तो FALSE वापस आ जाता है और जब तक फ़ंक्शन को @readfile () नहीं कहा जाता। एक त्रुटि संदेश मुद्रित होता है। " तो आप सामग्री के अंत में फ़ाइल + पूर्णांक संख्या की सामग्री के साथ समाप्त करेंगे।
म्लादेन बी।

22

पहले अपनी फ़ाइल प्रदर्शित करें और उसका मान url में सेट करें।

index.php

<a href="download.php?download='.$row['file'].'" title="Download File">

download.php

<?php
/*db connectors*/
include('dbconfig.php');

/*function to set your files*/
function output_file($file, $name, $mime_type='')
{
    if(!is_readable($file)) die('File not found or inaccessible!');
    $size = filesize($file);
    $name = rawurldecode($name);
    $known_mime_types=array(
        "htm" => "text/html",
        "exe" => "application/octet-stream",
        "zip" => "application/zip",
        "doc" => "application/msword",
        "jpg" => "image/jpg",
        "php" => "text/plain",
        "xls" => "application/vnd.ms-excel",
        "ppt" => "application/vnd.ms-powerpoint",
        "gif" => "image/gif",
        "pdf" => "application/pdf",
        "txt" => "text/plain",
        "html"=> "text/html",
        "png" => "image/png",
        "jpeg"=> "image/jpg"
    );

    if($mime_type==''){
        $file_extension = strtolower(substr(strrchr($file,"."),1));
        if(array_key_exists($file_extension, $known_mime_types)){
            $mime_type=$known_mime_types[$file_extension];
        } else {
            $mime_type="application/force-download";
        };
    };
    @ob_end_clean();
    if(ini_get('zlib.output_compression'))
    ini_set('zlib.output_compression', 'Off');
    header('Content-Type: ' . $mime_type);
    header('Content-Disposition: attachment; filename="'.$name.'"');
    header("Content-Transfer-Encoding: binary");
    header('Accept-Ranges: bytes');

    if(isset($_SERVER['HTTP_RANGE']))
    {
        list($a, $range) = explode("=",$_SERVER['HTTP_RANGE'],2);
        list($range) = explode(",",$range,2);
        list($range, $range_end) = explode("-", $range);
        $range=intval($range);
        if(!$range_end) {
            $range_end=$size-1;
        } else {
            $range_end=intval($range_end);
        }

        $new_length = $range_end-$range+1;
        header("HTTP/1.1 206 Partial Content");
        header("Content-Length: $new_length");
        header("Content-Range: bytes $range-$range_end/$size");
    } else {
        $new_length=$size;
        header("Content-Length: ".$size);
    }

    $chunksize = 1*(1024*1024);
    $bytes_send = 0;
    if ($file = fopen($file, 'r'))
    {
        if(isset($_SERVER['HTTP_RANGE']))
        fseek($file, $range);

        while(!feof($file) &&
            (!connection_aborted()) &&
            ($bytes_send<$new_length)
        )
        {
            $buffer = fread($file, $chunksize);
            echo($buffer);
            flush();
            $bytes_send += strlen($buffer);
        }
        fclose($file);
    } else
        die('Error - can not open file.');
    die();
}
set_time_limit(0);

/*set your folder*/
$file_path='uploads/'."your file";

/*output must be folder/yourfile*/

output_file($file_path, ''."your file".'', $row['type']);

/*back to index.php while downloading*/
header('Location:index.php');
?>

2
आपको यह कहां से मिला? यह शक्तिशाली लगता है
एक्सल ए। गार्सिया

@ jundell-agbo दिलचस्प और एक crt फ़ाइल के लिए?
फ्रेंल्बो

यह एक बहुत बड़ी फ़ाइल के लिए भी काम कर रहा है। महान समाधान। लेकिन `$ chunksize = 1 * (1024 * 1024);` धीमा है। मैंने कई मूल्यों के साथ कोशिश की और देखा कि `$ chunksize = 8 * (1024 * 1024);` सभी उपलब्ध बैंडविड्थ का उपयोग कर रहा है।
लिंग

16

यदि आपको किसी फ़ाइल को अनुमत मेमोरी लिमिट ( memory_limitआईएनआई सेटिंग) से बड़े आकार के साथ डाउनलोड करना है, जो PHP Fatal error: Allowed memory size of 5242880 bytes exhaustedत्रुटि का कारण होगा , तो आप ऐसा कर सकते हैं:

// File to download.
$file = '/path/to/file';

// Maximum size of chunks (in bytes).
$maxRead = 1 * 1024 * 1024; // 1MB

// Give a nice name to your download.
$fileName = 'download_file.txt';

// Open a file in read mode.
$fh = fopen($file, 'r');

// These headers will force download on browser,
// and set the custom file name for the download, respectively.
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $fileName . '"');

// Run this until we have read the whole file.
// feof (eof means "end of file") returns `true` when the handler
// has reached the end of file.
while (!feof($fh)) {
    // Read and output the next chunk.
    echo fread($fh, $maxRead);

    // Flush the output buffer to free memory.
    ob_flush();
}

// Exit to make sure not to output anything else.
exit;

मैंने बस यही कोशिश की और इसने मेरे सर्वर को मार दिया। मेरे लॉग में त्रुटियों की एक बड़ी संख्या लिखी।
डैनियल विलियम्स

यह जानना उपयोगी होगा कि लॉग किस बारे में थे।
परज़िफ़ल

क्षमा करें, लॉग फ़ाइल इतनी बड़ी हो गई थी कि मुझे इसे केवल nuke करना था, इसलिए मुझे देखने को नहीं मिला।
डैनियल विलियम्स

मुझे एक सर्वर पर कुछ इस तरह सेट करना पड़ रहा था जिसकी मुझे बहुत सीमित पहुँच थी। मेरी डाउनलोड स्क्रिप्ट होम पेज पर रीडायरेक्ट होती रही और मैं यह पता नहीं लगा सका कि क्यों। अब मुझे पता है कि समस्या एक मेमोरी त्रुटि थी और इस कोड ने इसे हल किया।
गाविं

यदि आप अभी उपयोग करते ob_flush()हैं तो त्रुटि हो सकती है: ob_flush (): बफर फ्लश करने में विफल। कोई बफर फ्लश करने के लिए । इसके साथ लपेटें if (ob_get_level() > 0) {ob_flush();}(संदर्भ stackoverflow.com/a/9182133/128761 )
vee

11

उपरोक्त स्वीकृत उत्तर का एक संशोधन, जो रनटाइम में MIME प्रकार का भी पता लगाता है:

$finfo = finfo_open(FILEINFO_MIME_TYPE);
header('Content-Type: '.finfo_file($finfo, $path));

$finfo = finfo_open(FILEINFO_MIME_ENCODING);
header('Content-Transfer-Encoding: '.finfo_file($finfo, $path)); 

header('Content-disposition: attachment; filename="'.basename($path).'"'); 
readfile($path); // do the double-download-dance (dirty but worky)

4

निम्न कोड php में डाउनलोड सेवा को लागू करने का एक सही तरीका है जैसा कि निम्नलिखित ट्यूटोरियल में बताया गया है

header('Content-Type: application/zip');
header("Content-Disposition: attachment; filename=\"$file_name\"");
set_time_limit(0);
$file = @fopen($filePath, "rb");
while(!feof($file)) {
    print(@fread($file, 1024*8));
    ob_flush();
    flush();
}

1
आपके पास इस कोड में दो चर हैं: file_nameऔर filePath। बहुत अच्छा कोडिंग अभ्यास नहीं है। खासकर बिना स्पष्टीकरण के। बाहरी ट्यूटोरियल से लिंक करना सहायक नहीं है।
खोम नाज़िद

2

इसे इस्तेमाल करे:

header('Content-type: audio/mp3'); 
header('Content-disposition: attachment; 
filename=“'.$trackname'”');                             
readfile('folder name /'.$trackname);          
exit();

2

http://php.net/manual/en/function.readfile.php

बस इतना ही चाहिए। "Monkey.gif" आपकी फ़ाइल के नाम में परिवर्तन करता है। यदि आपको अन्य सर्वर से डाउनलोड करने की आवश्यकता है, तो "monkey.gif" में " http://www.exsample.com/go.exe " परिवर्तन


1
StackOverflow में आपका स्वागत है। लिंक मुद्दों से बचने के लिए लिंक जोड़ने के बजाय सीधे कोड को शामिल करना हमेशा उचित होता है।
अजनबी

1

आप डाउनलोड भी स्ट्रीम कर सकते हैं जो काफी कम संसाधन का उपभोग करेगा। उदाहरण:

$readableStream = fopen('test.zip', 'rb');
$writableStream = fopen('php://output', 'wb');

header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="test.zip"');
stream_copy_to_stream($readableStream, $writableStream);
ob_flush();
flush();

उपरोक्त उदाहरण में, मैं एक test.zip डाउनलोड कर रहा हूं (जो वास्तव में मेरे स्थानीय मशीन पर एंड्रॉइड स्टूडियो ज़िप है)। php: // आउटपुट एक राइट-ओनली स्ट्रीम है (आमतौर पर इको या प्रिंट द्वारा उपयोग किया जाता है)। उसके बाद, आपको बस आवश्यक हेडर सेट करने और स्ट्रीम_कोपी_टो_स्ट्रीम (स्रोत, गंतव्य) को कॉल करने की आवश्यकता है। stream_copy_to_stream () विधि एक पाइप के रूप में कार्य करती है जो इनपुट को स्रोत स्ट्रीम (रीड स्ट्रीम) से लेती है और इसे गंतव्य स्ट्रीम (राइट स्ट्रीम) पर पाइप करती है और यह अनुमति दी गई मेमोरी के मुद्दे से भी बचती है ताकि आप वास्तव में बड़ी फ़ाइलों को डाउनलोड कर सकें अपने PHP की तुलना में memory_limit


डाउनलोड से क्या मतलब है?
पारस यजदानी

1
@ParsaYazdani इसका मतलब है कि डाउनलोड किए गए डेटा को ठुकरा दिया जाएगा। कृपया अधिक विवरण के लिए स्ट्रीमिंग की अवधारणा को देखें। नोट: यह PHP में फ़ाइल को स्ट्रीम (चंक) करने के लिए एकमात्र नहीं है। लेकिन यह निश्चित रूप से सबसे आसान तरीकों में से एक है।
सौद कुरैशी

0

मेरे ऊपर के जवाब काम करते हैं। लेकिन, मैं GET का उपयोग करके इसे कैसे निष्पादित करूं, इस पर एक विधि का योगदान करना चाहूंगा

अपने html / php पेज पर

$File = 'some/dir/file.jpg';
<a href="<?php echo '../sumdir/download.php?f='.$File; ?>" target="_blank">Download</a>

और download.phpइसमें शामिल है

$file = $_GET['f']; 

header("Expires: 0");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");

$ext = pathinfo($file, PATHINFO_EXTENSION);
$basename = pathinfo($file, PATHINFO_BASENAME);

header("Content-type: application/".$ext);
header('Content-length: '.filesize($file));
header("Content-Disposition: attachment; filename=\"$basename\"");
ob_clean(); 
flush();
readfile($file);
exit;

यह किसी भी फ़ाइल प्रकार पर काम करना चाहिए। यह POST का उपयोग करके परीक्षण नहीं किया गया है, लेकिन यह काम कर सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.