PHP में headers का उपयोग करके browser को file download करने के लिए बाध्य करने के तरीके।
विधि 1: Basic Force Download (किसी भी फाइल प्रकार के लिए)
<?php
function forceDownload($filePath, $fileName = null) {
if (!file_exists($filePath)) {
http_response_code(404);
die('File not found');
}
$fileName = $fileName ?? basename($filePath);
$fileSize = filesize($filePath);
$mimeType = mime_content_type($filePath);
// Cache headers साफ करें
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: private', false);
// Download headers
header('Content-Type: ' . $mimeType);
header('Content-Disposition: attachment; filename="' . $fileName . '"');
header('Content-Length: ' . $fileSize);
header('Content-Transfer-Encoding: binary');
// Output buffering साफ करें
if (ob_get_level()) {
ob_end_clean();
}
// File stream करें (memory efficient)
$handle = fopen($filePath, 'rb');
while (!feof($handle)) {
echo fread($handle, 8192);
flush();
}
fclose($handle);
exit;
}
// उपयोग
forceDownload('/path/to/document.pdf', 'my-document.pdf');
विधि 2: Specific MIME Types के लिए
<?php
// CSV download
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="export.csv"');
header('Pragma: no-cache');
header('Expires: 0');
echo $csvData;
exit;
// JSON download
header('Content-Type: application/json; charset=utf-8');
header('Content-Disposition: attachment; filename="data.json"');
echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
exit;
// Image download
header('Content-Type: image/jpeg');
header('Content-Disposition: attachment; filename="photo.jpg"');
readfile('photo.jpg');
exit;
विधि 3: .htaccess के साथ (सभी फाइलों के लिए)
# .htaccess में # सभी फाइलों को download के लिए force करेंForceType application/octet-stream Header set Content-Disposition "attachment" # या specific directory के लिएForceType application/octet-stream Header set Content-Disposition "attachment"
महत्वपूर्ण नोट्स और सर्वोत्तम अभ्यास
- कोई output नहीं headers से पहले (whitespace, BOM, echo कुछ भी नहीं)
- Large files के लिए:
readfile()या chunked reading उपयोग करें (memory limit से बचने के लिए) - Filename encoding: RFC 5987 के लिए
filename*=UTF-8''...उपयोग करें - Security: Path traversal रोकें -
basename()और वैलिडेशन उपयोग करें - Range requests: Resume support के लिए
HTTP_RANGEहैंडल करें
उन्नत: Range Requests Support (Resume Capable)
function forceDownloadWithRange($filePath, $fileName = null) {
$fileName = $fileName ?? basename($filePath);
$fileSize = filesize($filePath);
$mimeType = mime_content_type($filePath);
$start = 0;
$end = $fileSize - 1;
$statusCode = 200;
if (isset($_SERVER['HTTP_RANGE'])) {
$range = $_SERVER['HTTP_RANGE'];
if (preg_match('/bytes=(\d+)-(\d*)/', $range, $matches)) {
$start = intval($matches[1]);
$end = $matches[2] ? intval($matches[2]) : $fileSize - 1;
$statusCode = 206; // Partial Content
}
}
$length = $end - $start + 1;
header('Content-Type: ' . $mimeType);
header('Content-Disposition: attachment; filename="' . $fileName . '"');
header('Content-Length: ' . $length);
header('Accept-Ranges: bytes');
header('Content-Range: bytes ' . $start . '-' . $end . '/' . $fileSize);
http_response_code($statusCode);
$handle = fopen($filePath, 'rb');
fseek($handle, $start);
while (!feof($handle) && $length > 0) {
$chunk = min(8192, $length);
echo fread($handle, $chunk);
$length -= $chunk;
flush();
}
fclose($handle);
exit;
}